Date: Thu Mar 26 04:36:03 2020
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong
# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom
# * Phylum
# * Class
# * Order
# * Family
# * Genus
# * Species
# options(stringsAsFactors = FALSE,
# scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE,
# message = FALSE,
# warning = FALSE,
# error = FALSE)
# require(knitr)
# require(kableExtra)
# require(shiny)
require(phyloseq)
Loading required package: phyloseq
require(data.table)
Loading required package: data.table
data.table 1.12.2 using 18 threads (see ?getDTthreads). Latest news: r-datatable.com
require(ggplot2)
Loading required package: ggplot2
require(plotly)
Loading required package: plotly
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
require(DT)
Loading required package: DT
require(lmerTest)
Loading required package: lmerTest
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘lmerTest’
The following object is masked from ‘package:lme4’:
lmer
The following object is masked from ‘package:stats’:
step
require(nnet)
Loading required package: nnet
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE
Introduction
C57BL/6 wild-type (WT) and Nrf-2 double-knock-out (KO -/-) mice were given 2-week microbiome stabilization process using AIN93M diet and 8 more weeks to treat with either AIN93M or AIN93M 5% PEITC diet. Fecal samples were collected weekly, immediately frozen in liquid nitrogen and stored at -80oC. Serum, cecal, colon epithelial and whole colon tissues at week 10 were also collected for further analyses. Baseline, week 1 and 4 fecal samples were selected for 16s rRNA sequencing.
This document examines results from the WT mice samples.
We will attampt to answer the following questions:
1. Did microbiome change over time?
2. Was microbiome affected by diet?
3. Was there a difference between the KO and WT?
4. If there was a change in microbiome composition, what functional changes did it carry? What are the essential functions of the bacteria affected by the treatment and how can this be shown in vivo (metabolites, inflammation markers, etc.)?
Data preprocessing
Raw Data
FastQ files were downloaded from this Rutgers Box location. A total of 144 files (2 per sample, pair-ended) and a pair of undetermined reads were downloaded.
Samples
ps_sep2019@sam_data$Genotype_Week <- paste(ps_sep2019@sam_data$genotype,
ps_sep2019@sam_data$time,
sep = "_")
ps_sep2019@sam_data$ID <- factor(paste0(ps_sep2019@sam_data$mice_num,
ps_sep2019@sam_data$cage))
ps_sep2019@sam_data$TREATMENT <- paste0(ps_sep2019@sam_data$DSS,
ps_sep2019@sam_data$PEITC,
ps_sep2019@sam_data$cranberry)
ps_sep2019@sam_data$TREATMENT <- factor(ps_sep2019@sam_data$TREATMENT,
levels = c("000",
"100",
"110",
"101"),
labels = c("Naive",
"DSS",
"DSS+PEITC",
"DSS+Cranberry"))
samples <- ps_sep2019@sam_data
datatable(samples,
options = list(pageLength = nrow(samples)))
Prune data
The OTUs were mapped to Bacteria (96.07%), Eukaryota (2.95%) and Archea (0.03%) kingdoms, and 75 OTUs (0.95%) undefined.
The total of 7,867 unique sequences were found. Out of those, 7,558 were mapped to bacterial genomes.
dim(ps_sep2019@otu_table@.Data)
# Remove OTU not mapped to Bacteria
ps0 <- subset_taxa(ps_sep2019,
Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)
Out of the 7,558 OTUs 7,247 belonged to 12 Phyla. 311 of the OTUs (or 4.11% of bacterial OTUs) could not be mapped to a phylum.
t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
"Number of OTUs",
"Percent of OTUs")
datatable(t2,
rownames = FALSE,
caption = "Number of Bacterial OTUs by Phylum",
class = "cell-border stripe",
options = list(search = FALSE,
pageLength = nrow(t2))) %>%
formatCurrency(columns = 2,
currency = "",
mark = ",",
digits = 0) %>%
formatPercentage(columns = 3,
digits = 2)
OTU table (first 10 rows)
Total counts per sample (i.e. sequencing depth)
t1 <- colSums(otu[, 7:ncol(otu)])
t1 <- data.table(SAMPLE_NAME = names(t1),
Total = t1)
t2 <- data.table(SAMPLE_NAME = rownames(samples),
ID = samples$ID,
CAGE = samples$cage,
TREATMENT = samples$TREATMENT,
Genotype = samples$genotype,
WEEK = samples$time)
smpl <- merge(t1,
t2,
by = "SAMPLE_NAME")
p1 <- ggplot(smpl,
aes(x = SAMPLE_NAME,
y = Total,
fill = TREATMENT,
colour = WEEK)) +
facet_wrap(~ Genotype,
scale = "free_x") +
geom_bar(stat = "identity") +
scale_x_discrete("") +
scale_y_continuous("Number of Reads") +
scale_fill_discrete("Treatment") +
theme(axis.text.x = element_text(angle = 45,
hjust = 1))
ggplotly(p1)
tmp <- copy(smpl)
tmp$WEEK <- factor(tmp$WEEK,
levels = c("baseline",
"week1",
"week8"),
labels = c("Week 0",
"Week 1",
"Week 8"))
tmp$Genotype <- factor(tmp$Genotype,
levels = c("widetype",
"nrf2KO"),
labels = c("Wild Type",
"Nrf2 KO"))
p1 <- ggplot(tmp,
aes(x = SAMPLE_NAME,
y = Total,
group = TREATMENT,
fill = TREATMENT)) +
facet_wrap(~ Genotype + WEEK,
scale = "free_x") +
geom_bar(stat = "identity",
color = "black") +
scale_x_discrete("") +
scale_y_continuous("Number of Reads") +
scale_fill_grey("Treatment",
start = 0.1,
end = 1,
na.value = "red",
aesthetics = "fill") +
theme_bw() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.position = "top")
tiff(filename = "tmp/seq_depth.tiff",
height = 6,
width = 6,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
print(p1)
Richness (Alpha diversity)
Shannon index (aka Shannon enthrophy) is calculated as:
H’ = -sum(1 to R)p(i)ln(p(i)) When there is exactly 1 type of data (e.g. a single species in the sample), H’=0. The opposite scenario is when there are R>1 species present in the sample in the exact same amounts and H’=ln(R).
Shannon’s diversity index was calculated for each sample and ploted over time using the 7,764 from the 13 Phylum above.
shannon.ndx <- estimate_richness(ps0,
measures = "Shannon")
shannon.ndx <- data.table(SAMPLE_NAME = rownames(shannon.ndx),
shannon.ndx)
smpl <- merge(smpl,
shannon.ndx,
by = "SAMPLE_NAME")
p1 <- ggplot(smpl,
aes(x = Total,
y = Shannon,
fill = Genotype,
shape = WEEK)) +
geom_point(size = 2) +
scale_shape_manual(breaks = unique(smpl$WEEK),
values = 21:23)
tiff(filename = "tmp/shannon_vs_depth.tiff",
height = 5,
width = 6,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
Even though estimate_richness function does not adjust for the sequencing depth, there is no correlation between the index and the sample’s sequecing depth. Proceed with the comparison.
Shannon idex over time
p1 <- plot_richness(ps0,
x = "time",
measures = "Shannon") +
facet_wrap(~ genotype) +
geom_line(aes(group = ID),
color = "black") +
geom_point(aes(fill = TREATMENT),
shape = 21,
size = 3,
color = "black") +
scale_x_discrete("") +
theme(axis.text.x = element_text(angle = 30,
hjust = 1,
vjust = 1))
ggplotly(p = p1,
tooltip = c("ID",
"value"))
p1 <- p1 +
scale_fill_discrete("") +
theme(legend.position = "top")
tiff(filename = "tmp/shannon.tiff",
height = 4,
width = 5,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
The plot above suggests that the largest differences in alpha diversity (as measured by Shannon’s index) are in genotype.
Average Shannon Index
# Average shannon index by treatment group
tmp <- copy(smpl)
tmp[, mu := mean(Shannon),
by = list(TREATMENT,
Genotype,
WEEK)]
tmp[, sem := sd(Shannon)/sqrt(.N),
by = list(TREATMENT,
Genotype,
WEEK)]
tmp <- unique(tmp[, c("TREATMENT",
"Genotype",
"WEEK",
"mu",
"sem")])
tmp$WEEK <- factor(tmp$WEEK,
levels = c("baseline",
"week1",
"week8"),
labels = c("Week 0",
"Week 1",
"Week 8"))
tmp$Genotype <- factor(tmp$Genotype,
levels = c("widetype",
"nrf2KO"),
labels = c("Wild Type",
"Nrf2 KO"))
p1 <- ggplot(tmp,
aes(x = WEEK,
y = mu,
ymin = mu - sem,
ymax = mu + sem,
fill = TREATMENT,
group = TREATMENT)) +
facet_wrap(~ Genotype) +
geom_errorbar(position = position_dodge(0.4),
width = 0.4) +
geom_line(position = position_dodge(0.4)) +
geom_point(size = 3,
shape = 21,
position = position_dodge(0.4)) +
scale_x_discrete("") +
scale_y_continuous("Shannon Index") +
theme(axis.text.x = element_text(angle = 45,
hjust = 1),
legend.position = "top")
tiff(filename = "tmp/avg_shannon.tiff",
height = 5,
width = 6,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
print(p1)
Test if the richness changed between the baseline and Week 8.
smpl$TREATMENT <- factor(smpl$TREATMENT,
levels = c("DSS",
"Naive",
"DSS+PEITC",
"DSS+Cranberry"))
tmp <- droplevels(smpl[WEEK != "week1"])
m1 <- lm(Shannon ~ WEEK*(TREATMENT + Genotype),
# offset = Total,
data = tmp)
summary(m1)
Call:
lm(formula = Shannon ~ WEEK * (TREATMENT + Genotype), data = tmp)
Residuals:
Min 1Q Median 3Q Max
-0.316186 -0.091027 0.007886 0.110704 0.293230
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.94987 0.07064 84.233 < 2e-16 ***
WEEKweek8 0.01158 0.09989 0.116 0.9084
TREATMENTNaive 0.14581 0.08935 1.632 0.1109
TREATMENTDSS+PEITC -0.03923 0.08935 -0.439 0.6631
TREATMENTDSS+Cranberry -0.22582 0.08935 -2.527 0.0158 *
Genotypewidetype -0.54156 0.06318 -8.572 2.06e-10 ***
WEEKweek8:TREATMENTNaive 0.01181 0.12636 0.093 0.9261
WEEKweek8:TREATMENTDSS+PEITC 0.01652 0.12636 0.131 0.8966
WEEKweek8:TREATMENTDSS+Cranberry 0.21535 0.12636 1.704 0.0965 .
WEEKweek8:Genotypewidetype 0.23085 0.08935 2.584 0.0137 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1548 on 38 degrees of freedom
Multiple R-squared: 0.7845, Adjusted R-squared: 0.7335
F-statistic: 15.37 on 9 and 38 DF, p-value: 3.671e-10
m2 <- lmer(Shannon ~ WEEK*(TREATMENT + Genotype) + (1 | ID),
# offset = Total,
data = tmp)
summary(m2)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: Shannon ~ WEEK * (TREATMENT + Genotype) + (1 | ID)
Data: tmp
REML criterion at convergence: -22.2
Scaled residuals:
Min 1Q Median 3Q Max
-1.53721 -0.47495 0.06753 0.44489 1.53874
Random effects:
Groups Name Variance Std.Dev.
ID (Intercept) 0.01259 0.1122
Residual 0.01136 0.1066
Number of obs: 48, groups: ID, 24
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 5.94987 0.07064 29.76837 84.233 < 2e-16 ***
WEEKweek8 0.01158 0.06879 19.00000 0.168 0.86814
TREATMENTNaive 0.14581 0.08935 29.76837 1.632 0.11322
TREATMENTDSS+PEITC -0.03923 0.08935 29.76837 -0.439 0.66379
TREATMENTDSS+Cranberry -0.22582 0.08935 29.76837 -2.527 0.01704 *
Genotypewidetype -0.54156 0.06318 29.76837 -8.572 1.55e-09 ***
WEEKweek8:TREATMENTNaive 0.01181 0.08701 19.00000 0.136 0.89350
WEEKweek8:TREATMENTDSS+PEITC 0.01652 0.08701 19.00000 0.190 0.85139
WEEKweek8:TREATMENTDSS+Cranberry 0.21535 0.08701 19.00000 2.475 0.02291 *
WEEKweek8:Genotypewidetype 0.23085 0.06152 19.00000 3.752 0.00135 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) WEEKw8 TREATMENTN TREATMENTDSS+P TREATMENTDSS+C Gntypw
WEEKweek8 -0.487
TREATMENTNv -0.632 0.308
TREATMENTDSS+P -0.632 0.308 0.500
TREATMENTDSS+C -0.632 0.308 0.500 0.500
Gentypwdtyp -0.447 0.218 0.000 0.000 0.000
WEEK8:TREATMENTN 0.308 -0.632 -0.487 -0.243 -0.243 0.000
WEEK8:TREATMENTDSS+P 0.308 -0.632 -0.243 -0.487 -0.243 0.000
WEEK8:TREATMENTDSS+C 0.308 -0.632 -0.243 -0.243 -0.487 0.000
WEEKwk8:Gnt 0.218 -0.447 0.000 0.000 0.000 -0.487
WEEK8:TREATMENTN WEEK8:TREATMENTDSS+P WEEK8:TREATMENTDSS+C
WEEKweek8
TREATMENTNv
TREATMENTDSS+P
TREATMENTDSS+C
Gentypwdtyp
WEEK8:TREATMENTN
WEEK8:TREATMENTDSS+P 0.500
WEEK8:TREATMENTDSS+C 0.500 0.500
WEEKwk8:Gnt 0.000 0.000 0.000
Calculate change in Shannon index from baseline
dd <- smpl
dd[, delta := Shannon - Shannon[WEEK == "baseline"],
by = ID]
dd$diff <- paste(dd$WEEK,
"-baseline",
sep = "")
dd <- dd[WEEK != "baseline",]
p1 <- ggplot(dd,
aes(x = TREATMENT,
y = delta,
fill = Genotype)) +
facet_wrap(~ diff) +
geom_hline(yintercept = 0,
linetype = "dashed") +
geom_point(position = position_dodge(0.3),
shape = 21,
size = 3) +
scale_y_continuous("Shannon Index Percent Change from Baseline") +
theme(axis.text.x = element_text(angle = 45,
hjust = 1))
print(p1)

dd$TREATMENT <- factor(dd$TREATMENT,
levels = c("DSS",
"Naive",
"DSS+PEITC",
"DSS+Cranberry"))
dd$Genotype <- factor(dd$Genotype,
levels = c("widetype",
"nrf2KO"))
m1 <- lm(delta ~ TREATMENT*Genotype,
data = dd)
summary(m1)
Call:
lm(formula = delta ~ TREATMENT * Genotype, data = dd)
Residuals:
Min 1Q Median 3Q Max
-0.40513 -0.09560 -0.02012 0.09568 0.35517
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.25142 0.07286 3.451 0.00133 **
TREATMENTNaive -0.04426 0.10303 -0.430 0.66985
TREATMENTDSS+PEITC -0.15777 0.10303 -1.531 0.13358
TREATMENTDSS+Cranberry 0.04463 0.10303 0.433 0.66720
Genotypenrf2KO -0.18412 0.10303 -1.787 0.08153 .
TREATMENTNaive:Genotypenrf2KO -0.02851 0.14571 -0.196 0.84586
TREATMENTDSS+PEITC:Genotypenrf2KO 0.24747 0.14571 1.698 0.09721 .
TREATMENTDSS+Cranberry:Genotypenrf2KO 0.07927 0.14571 0.544 0.58946
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1785 on 40 degrees of freedom
Multiple R-squared: 0.249, Adjusted R-squared: 0.1176
F-statistic: 1.894 on 7 and 40 DF, p-value: 0.09608
# No significant interactions, proceed with 2-way analysis
m2 <- lm(delta ~ TREATMENT + Genotype,
data = dd)
summary(m2)
Call:
lm(formula = delta ~ TREATMENT + Genotype, data = dd)
Residuals:
Min 1Q Median 3Q Max
-0.49158 -0.09742 -0.01290 0.11101 0.35281
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.21414 0.05849 3.661 0.000683 ***
TREATMENTNaive -0.05851 0.07399 -0.791 0.433377
TREATMENTDSS+PEITC -0.03404 0.07399 -0.460 0.647813
TREATMENTDSS+Cranberry 0.08427 0.07399 1.139 0.261014
Genotypenrf2KO -0.10956 0.05232 -2.094 0.042176 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1812 on 43 degrees of freedom
Multiple R-squared: 0.1674, Adjusted R-squared: 0.08999
F-statistic: 2.162 on 4 and 43 DF, p-value: 0.08947
At Week 8 there was significantly smaller increase of alpha diversity from baseline in Nrf2 KO compared to WT, and in DSS+Cranberry compared to DSS only.
Load aminoacids
aa <- fread("data_sep2019/sep2019_aminoacids.csv")
aa <- aa[!is.na(ID), ]
aa$ID <- paste0(aa$ID,
aa$CAGE)
smpl1 <- unique(smpl[, c("ID",
"TREATMENT",
"Genotype")])
smpl1$ID <- as.character(smpl1$ID)
aa <- merge(smpl1,
aa,
by = "ID")
aa[, trt_week := paste(TREATMENT,
WEEK,
sep = "_")]
aa$trt_week <- factor(aa$trt_week,
levels = c("Naive_week2",
"Naive_week6",
"DSS_week2",
"DSS_week6",
"DSS+Cranberry_week2",
"DSS+Cranberry_week6" ,
"DSS+PEITC_week2",
"DSS+PEITC_week6"))
Aminoacids by animal, treatment group and timepoint
for (i in 8:(ncol(aa) - 1)) {
tmp <- aa[, c(1, 3, 7, ncol(aa), i), with = FALSE]
colnames(tmp)[5] <- "Y"
p1 <- ggplot(tmp,
aes(x = trt_week,
y = Y,
fill = Genotype,
group = ID)) +
geom_line(position = position_dodge(0.3)) +
geom_point(shape = 21,
size = 3,
position = position_dodge(0.3)) +
scale_x_discrete("") +
scale_y_continuous(colnames(aa)[i]) +
theme(axis.text.x = element_text(angle = 45,
hjust = 1))
# tiff(filename = paste0("tmp/",
# colnames(aa)[i],
# ".tiff"),
# height = 4,
# width = 5,
# units = "in",
# res = 600,
# compression = "lzw+p")
# print(p1)
# graphics.off()
print(p1)
}




















Aminoacids over time, group averages
out <- list()
for (i in 8:27) {
tmp <- aa[, c(2, 3, 7, i),
with = FALSE]
names(tmp)[4] <- "val"
tmp[, mu := mean(val,
na.rm = TRUE),
by = list(TREATMENT,
Genotype,
WEEK)]
tmp[, sem := sd(val,
na.rm = TRUE)/sqrt(.N),
by = list(TREATMENT,
Genotype,
WEEK)]
out[[i - 7]] <- data.table(Aminoacid = names(aa)[i],
unique(tmp[, c("TREATMENT",
"Genotype",
"WEEK",
"mu",
"sem")]))
}
muaa <- rbindlist(out)
muaa$Aminoacid <- factor(muaa$Aminoacid,
levels = unique(muaa$Aminoacid))
muaa$Genotype <- factor(muaa$Genotype,
levels = c("widetype",
"nrf2KO"),
labels = c("Wild Type",
"Nrf2 KO"))
for (i in 1:nlevels(muaa$Aminoacid)) {
p1 <- ggplot(muaa[Aminoacid == levels(muaa$Aminoacid)[i], ],
aes(x = WEEK,
y = mu,
ymin = mu - sem,
ymax = mu + sem,
fill = TREATMENT,
group = TREATMENT)) +
facet_wrap(~ Genotype) +
geom_errorbar(position = position_dodge(0.4),
width = 0.4) +
geom_line(position = position_dodge(0.4)) +
geom_point(size = 3,
shape = 21,
position = position_dodge(0.4)) +
scale_x_discrete("",
breaks = c("week2",
"week6"),
labels = c("Week 2",
"Week 6")) +
scale_y_continuous(levels(muaa$Aminoacid)[i]) +
theme(axis.text.x = element_text(angle = 45,
hjust = 1),
legend.position = "top")
# tiff(filename = paste0("tmp/avg_",
# levels(muaa$Aminoacid)[i],
# ".tiff"),
# height = 5,
# width = 6,
# units = "in",
# res = 600,
# compression = "lzw+p")
# print(p1)
# graphics.off()
print(p1)
}




















Aminoacid data PCA
dt_pca <- aa[, Alanine:glutamine]
# m1 <- prcomp(dt_pca,
# center = TRUE,
# scale. = TRUE)
# m1 <- prcomp(dt_pca,
# center = FALSE,
# scale. = FALSE)
m1 <- prcomp(dt_pca)
summary(m1)
Importance of components:
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8
Standard deviation 4.8108 2.5833 1.78182 1.13495 0.93367 0.84949 0.62035 0.49052
Proportion of Variance 0.6276 0.1810 0.08609 0.03493 0.02364 0.01957 0.01044 0.00652
Cumulative Proportion 0.6276 0.8086 0.89466 0.92959 0.95323 0.97280 0.98323 0.98976
PC9 PC10 PC11 PC12 PC13 PC14 PC15 PC16
Standard deviation 0.35960 0.26786 0.22940 0.20322 0.1486 0.13250 0.11932 0.11154
Proportion of Variance 0.00351 0.00195 0.00143 0.00112 0.0006 0.00048 0.00039 0.00034
Cumulative Proportion 0.99326 0.99521 0.99663 0.99775 0.9983 0.99883 0.99922 0.99955
PC17 PC18 PC19 PC20
Standard deviation 0.08896 0.07274 0.05110 0.02565
Proportion of Variance 0.00021 0.00014 0.00007 0.00002
Cumulative Proportion 0.99977 0.99991 0.99998 1.00000
# Select PC-s to pliot (PC1 & PC2)
choices <- 1:2
# Scores, i.e. points (df.u)
dt.scr <- data.table(m1$x[, choices])
# Add grouping variable
dt.scr$grp <- aa$trt_week
dt.scr$TREATMENT <- aa$TREATMENT
dt.scr$WEEK <- aa$WEEK
dt.scr
# Loadings, i.e. arrows (df.v)
dt.rot <- as.data.frame(m1$rotation[, choices])
dt.rot$feat <- rownames(dt.rot)
dt.rot <- data.table(dt.rot)
dt.rot
dt.load <- melt.data.table(dt.rot,
id.vars = "feat",
measure.vars = 1:2,
variable.name = "pc",
value.name = "loading")
dt.load$feat <- factor(dt.load$feat,
levels = unique(dt.load$feat))
# Plot loadings
p0 <- ggplot(data = dt.load,
aes(x = feat,
y = loading)) +
facet_wrap(~ pc,
nrow = 2) +
geom_bar(stat = "identity") +
ggtitle("PC Loadings") +
theme(plot.title = element_text(hjust = 0.5),
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/pc.1.2_loadings.tiff",
height = 5,
width = 8,
units = 'in',
res = 300,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

# Axis labels
u.axis.labs <- paste(colnames(dt.rot)[1:2],
sprintf('(%0.1f%% explained var.)',
100*m1$sdev[choices]^2/sum(m1$sdev^2)))
u.axis.labs
[1] "PC1 (62.8% explained var.)" "PC2 (18.1% explained var.)"
# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = grp),
shape = 21,
size = 2,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 10*PC1,
yend = 10*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
# size = 1,
color = "black") +
geom_text(aes(x = 11*PC1,
y = 11*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_discrete(name = "Group") +
ggtitle("Biplot of Aminoacids") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
tiff(filename = "tmp/aminoacids_biplot.tiff",
height = 10,
width = 10,
units = 'in',
res = 300,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
p2 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = WEEK),
shape = 21,
size = 2,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 10*PC1,
yend = 10*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
size = 1.2,
color = "black") +
geom_text(aes(x = 11*PC1,
y = 11*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_discrete(name = "Week") +
ggtitle("Biplot of Aminoacids") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
tiff(filename = "tmp/aminoacids_by_week_biplot.tiff",
height = 10,
width = 10,
units = 'in',
res = 300,
compression = "lzw+p")
print(p2)
graphics.off()
ggplotly(p2)
p2 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = TREATMENT),
shape = 21,
size = 2,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 10*PC1,
yend = 10*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
size = 1.2,
color = "black") +
geom_text(aes(x = 11*PC1,
y = 11*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_discrete(name = "Treatment") +
ggtitle("Biplot of Aminoacids") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
tiff(filename = "tmp/aminoacids_by_trt_biplot.tiff",
height = 10,
width = 10,
units = 'in',
res = 300,
compression = "lzw+p")
print(p2)
graphics.off()
ggplotly(p2)
Remove unmapped OTUs
The 311 unmapped OTUs were removed from further analysis (with 7,247 OTUs left).
ps1 <- subset_taxa(ps0,
!is.na(Phylum))
dim(ps1@otu_table@.Data)
[1] 72 7247
Relative abundance (%) at Phylum level
Remove phyla with relative abundance of >= 1% in less than 10% of samples.
t1 <- data.table(Phylum = ra_p$Phylum,
`Number of Samples` = rowSums(ra_p[, 2:ncol(ra_p)] >= 0.01))
t1$`Percent Samples` <- t1$`Number of Samples`/72
setorder(t1, -`Number of Samples`)
datatable(t1,
rownames = FALSE,
caption = "Taxonomic count table",
class = "cell-border stripe",
options = list(search = FALSE,
pageLength = nrow(t1))) %>%
formatPercentage(columns = 3,
digits = 1)
We will remove Chlamydiae from this analysis.
[1] "Firmicutes, Bacteroidetes, Proteobacteria, Verrucomicrobia, Epsilonbacteraeota, Actinobacteria, Deferribacteres, Patescibacteria, Cyanobacteria"
7,224 OTUs, down from 7,247 OTUs in the previous table.
Relative Abundance in Samples at Different Taxonomic Ranks
PCA at Class level
dt_pca <- t(ra_c[, 3:ncol(ra_c)])
colnames(dt_pca) <- ra_c$Class
dt_pca_c <- data.table(SAMPLE_NAME = rownames(dt_pca),
dt_pca)
dt_pca_c <- merge(smpl,
dt_pca_c,
by = "SAMPLE_NAME")
# m1 <- prcomp(dt_pca,
# center = TRUE,
# scale. = TRUE)
# m1 <- prcomp(dt_pca,
# center = FALSE,
# scale. = FALSE)
m1 <- prcomp(dt_pca)
summary(m1)
Importance of components:
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8
Standard deviation 14.6908 8.5044 7.5927 5.76824 3.41220 2.73038 2.43631 1.46850
Proportion of Variance 0.5294 0.1774 0.1414 0.08162 0.02856 0.01829 0.01456 0.00529
Cumulative Proportion 0.5294 0.7068 0.8482 0.92987 0.95844 0.97672 0.99128 0.99657
PC9 PC10 PC11 PC12 PC13 PC14
Standard deviation 0.93207 0.55762 0.43780 0.15826 0.02399 8.187e-17
Proportion of Variance 0.00213 0.00076 0.00047 0.00006 0.00000 0.000e+00
Cumulative Proportion 0.99870 0.99947 0.99994 1.00000 1.00000 1.000e+00
# Select PC-s to pliot (PC1 & PC2)
choices <- 1:2
# Scores, i.e. points (df.u)
dt.scr <- data.table(m1$x[, choices])
# Add grouping variable
dt.scr$grp <- paste(dt_pca_c$TREATMENT,
dt_pca_c$WEEK,
dt_pca_c$Genotype)
dt.scr$TREATMENT <- dt_pca_c$TREATMENT
dt.scr$WEEK <- dt_pca_c$WEEK
dt.scr$Genotype <- dt_pca_c$Genotype
dt.scr
# Loadings, i.e. arrows (df.v)
dt.rot <- as.data.frame(m1$rotation[, choices])
dt.rot$feat <- rownames(dt.rot)
dt.rot <- data.table(dt.rot)
dt.rot
dt.load <- melt.data.table(dt.rot,
id.vars = "feat",
measure.vars = 1:2,
variable.name = "pc",
value.name = "loading")
dt.load$feat <- factor(dt.load$feat,
levels = unique(dt.load$feat))
# Plot loadings
p0 <- ggplot(data = dt.load,
aes(x = feat,
y = loading)) +
facet_wrap(~ pc,
nrow = 2) +
geom_bar(stat = "identity") +
ggtitle("PC Loadings") +
theme(plot.title = element_text(hjust = 0.5),
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/pc.1.2_loadings_class.tiff",
height = 5,
width = 8,
units = 'in',
res = 300,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

# Axis labels
u.axis.labs <- paste(colnames(dt.rot)[1:2],
sprintf('(%0.1f%% explained var.)',
100*m1$sdev[choices]^2/sum(m1$sdev^2)))
u.axis.labs
[1] "PC1 (52.9% explained var.)" "PC2 (17.7% explained var.)"
# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = grp),
shape = 21,
size = 2,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 40*PC1,
yend = 40*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
# size = 1,
color = "black") +
geom_text(aes(x = 44*PC1,
y = 44*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_discrete(name = "Group") +
ggtitle("Biplot of Classes of Bacteria") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
tiff(filename = "tmp/class_biplot_grp.tiff",
height = 10,
width = 10,
units = 'in',
res = 300,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
# Find centers of each group
grpg <- "grp"
var1 <- eval(parse(text = paste("dt.scr$",
grpg,
sep = "")))
cntr <- data.table(Group = unique(var1),
PC1 = aggregate(x = dt.scr$PC1,
by = list(var1),
FUN = "mean")$x,
PC2 = aggregate(x = dt.scr$PC2,
by = list(var1),
FUN = "mean")$x)
p2 <- p1 + geom_label(data = cntr,
aes(x = PC1,
y = PC2,
label = Group,
colour = Group),
alpha = 0.5,
size = 3) +
scale_color_discrete(guide = FALSE) +
theme(legend.position = "none")
print(p2)

# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = Genotype),
shape = 21,
size = 2,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 40*PC1,
yend = 40*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
# size = 1,
color = "black") +
geom_text(aes(x = 44*PC1,
y = 44*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_discrete(name = "Group") +
ggtitle("Biplot of Classes of Bacteria") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
tiff(filename = "tmp/class_biplot_genotype.tiff",
height = 10,
width = 10,
units = 'in',
res = 300,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
# Find centers of each group
grpg <- "Genotype"
var1 <- eval(parse(text = paste("dt.scr$",
grpg,
sep = "")))
cntr <- data.table(Group = unique(var1),
PC1 = aggregate(x = dt.scr$PC1,
by = list(var1),
FUN = "mean")$x,
PC2 = aggregate(x = dt.scr$PC2,
by = list(var1),
FUN = "mean")$x)
p2 <- p1 + geom_label(data = cntr,
aes(x = PC1,
y = PC2,
label = Group,
colour = Group),
alpha = 0.5,
size = 3) +
scale_color_discrete(guide = FALSE) +
theme(legend.position = "none")
print(p2)

# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = WEEK),
shape = 21,
size = 2,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 40*PC1,
yend = 40*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
# size = 1,
color = "black") +
geom_text(aes(x = 44*PC1,
y = 44*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_discrete(name = "Group") +
ggtitle("Biplot of Classes of Bacteria") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
tiff(filename = "tmp/class_biplot_week.tiff",
height = 10,
width = 10,
units = 'in',
res = 300,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
# Find centers of each group
grpg <- "WEEK"
var1 <- eval(parse(text = paste("dt.scr$",
grpg,
sep = "")))
cntr <- data.table(Group = unique(var1),
PC1 = aggregate(x = dt.scr$PC1,
by = list(var1),
FUN = "mean")$x,
PC2 = aggregate(x = dt.scr$PC2,
by = list(var1),
FUN = "mean")$x)
p2 <- p1 + geom_label(data = cntr,
aes(x = PC1,
y = PC2,
label = Group,
colour = Group),
alpha = 0.5,
size = 3) +
scale_color_discrete(guide = FALSE) +
theme(legend.position = "none")
print(p2)

# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
aes(x = PC1,
y = PC2)) +
coord_equal() +
geom_point(data = dt.scr,
aes(fill = TREATMENT),
shape = 21,
size = 3,
alpha = 0.5) +
geom_segment(aes(x = 0,
y = 0,
xend = 40*PC1,
yend = 40*PC2),
arrow = arrow(length = unit(1/2, 'picas')),
# size = 1,
color = "black") +
geom_text(aes(x = 44*PC1,
y = 44*PC2,
label = dt.rot$feat),
# size = 5,
hjust = 0.5) +
scale_x_continuous(u.axis.labs[1]) +
scale_y_continuous(u.axis.labs[2]) +
scale_fill_manual(name = "Treatment",
breaks = levels(dt.scr$TREATMENT),
values = c("red",
"green",
"orange",
"blue")) +
ggtitle("Biplot of Classes of Bacteria") +
theme(plot.title = element_text(hjust = 0.5,
size = 20))
ggplotly(p1)
# Find centers of each group
# grpg <- "TREATMENT"
# var1 <- eval(parse(text = paste("dt.scr$",
# grpg,
# sep = "")))
# cntr <- data.table(Group = levels(var1),
# PC1 = aggregate(x = dt.scr$PC1,
# by = list(var1),
# FUN = "mean")$x,
# PC2 = aggregate(x = dt.scr$PC2,
# by = list(var1),
# FUN = "mean")$x)
cntr <- data.table(PC1 = aggregate(x = dt.scr$PC1,
by = list(dt.scr$TREATMENT),
FUN = "mean"),
PC2 = aggregate(x = dt.scr$PC2,
by = list(var1),
FUN = "mean")$x)
colnames(cntr) <- c("TREATMENT",
"PC1",
"PC2")
p2 <- p1 + geom_label(data = cntr,
aes(x = PC1,
y = PC2,
label = TREATMENT,
colour = TREATMENT),
alpha = 0.5,
size = 3) +
scale_color_manual(guide = FALSE,
breaks = levels(cntr$TREATMENT),
values = c("red",
"green",
"orange",
"blue")) +
theme(legend.position = "none")
tiff(filename = "tmp/class_biplot_trt.tiff",
height = 8,
width = 8,
units = 'in',
res = 300,
compression = "lzw+p")
print(p2)
graphics.off()
print(p2)

# Covariates only
m1 <- multinom(TREATMENT ~ WEEK + Genotype,
data = dt.scr)
# weights: 20 (12 variable)
initial value 99.813194
final value 99.813194
converged
summary(m1)
Call:
multinom(formula = TREATMENT ~ WEEK + Genotype, data = dt.scr)
Coefficients:
(Intercept) WEEKweek1 WEEKweek8 Genotypewidetype
Naive 0 0 0 0
DSS+PEITC 0 0 0 0
DSS+Cranberry 0 0 0 0
Std. Errors:
(Intercept) WEEKweek1 WEEKweek8 Genotypewidetype
Naive 0.6666667 0.8164966 0.8164966 0.6666667
DSS+PEITC 0.6666667 0.8164966 0.8164966 0.6666667
DSS+Cranberry 0.6666667 0.8164966 0.8164966 0.6666667
Residual Deviance: 199.6264
AIC: 223.6264
prd1 <- predict(m1)
t1 <- table(Predicted = prd1,
Observed = dt.scr$TREATMENT)
# PC1 alone
m2 <- multinom(TREATMENT ~ PC1,
data = dt.scr)
# weights: 12 (6 variable)
initial value 99.813194
iter 10 value 84.652280
final value 84.650617
converged
summary(m2)
Call:
multinom(formula = TREATMENT ~ PC1, data = dt.scr)
Coefficients:
(Intercept) PC1
Naive -0.84291965 -0.13135533
DSS+PEITC 0.02563488 -0.01778110
DSS+Cranberry -0.28377674 0.04267039
Std. Errors:
(Intercept) PC1
Naive 0.5329226 0.03966130
DSS+PEITC 0.3375675 0.02567473
DSS+Cranberry 0.3902129 0.02668075
Residual Deviance: 169.3012
AIC: 181.3012
prd2 <- predict(m2)
t2 <- table(Predicted = prd2,
Observed = dt.scr$TREATMENT)
# PC1 with covariates
m3 <- multinom(TREATMENT ~ PC1 + WEEK + Genotype,
data = dt.scr)
# weights: 24 (15 variable)
initial value 99.813194
iter 10 value 78.199054
final value 77.966110
converged
summary(m3)
Call:
multinom(formula = TREATMENT ~ PC1 + WEEK + Genotype, data = dt.scr)
Coefficients:
(Intercept) PC1 WEEKweek1 WEEKweek8 Genotypewidetype
Naive -1.69181404 -0.16561286 -0.19417414 -0.2467395 2.0439498
DSS+PEITC -0.22775882 -0.03756158 -0.03426154 -0.1624952 0.6998366
DSS+Cranberry 0.04994931 0.11984007 0.18496264 0.6354061 -2.2783047
Std. Errors:
(Intercept) PC1 WEEKweek1 WEEKweek8 Genotypewidetype
Naive 0.9208565 0.04798080 1.0184358 0.9866132 1.0821427
DSS+PEITC 0.7006164 0.03813898 0.8248932 0.8419015 0.9838589
DSS+Cranberry 0.7578087 0.04894181 0.8842508 0.9154535 1.1724461
Residual Deviance: 155.9322
AIC: 185.9322
prd3 <- predict(m3)
t3 <- table(Predicted = prd3,
Observed = dt.scr$TREATMENT)
# PC1 + PC2 with covariates
m4 <- multinom(TREATMENT ~ PC1 + PC2 + WEEK + Genotype,
data = dt.scr)
# weights: 28 (18 variable)
initial value 99.813194
iter 10 value 77.643401
iter 20 value 76.157664
final value 76.157652
converged
summary(m4)
Call:
multinom(formula = TREATMENT ~ PC1 + PC2 + WEEK + Genotype, data = dt.scr)
Coefficients:
(Intercept) PC1 PC2 WEEKweek1 WEEKweek8 Genotypewidetype
Naive -1.6723699 -0.16055402 0.02692425 0.0603261 -0.04440483 1.7116558
DSS+PEITC -0.1610640 -0.03200954 -0.04731926 -0.3059877 -0.35846181 0.6645649
DSS+Cranberry -0.1487237 0.11347301 0.04018812 0.3641810 0.72081476 -2.0106669
Std. Errors:
(Intercept) PC1 PC2 WEEKweek1 WEEKweek8 Genotypewidetype
Naive 0.9329651 0.04827333 0.04795722 1.1064244 1.0330649 1.083235
DSS+PEITC 0.7176961 0.03961699 0.04860606 0.8745219 0.8762840 1.022935
DSS+Cranberry 0.8377326 0.04936837 0.06510574 0.9608816 0.9434467 1.204373
Residual Deviance: 152.3153
AIC: 188.3153
prd4 <- predict(m4)
t4 <- table(Predicted = prd4,
Observed = dt.scr$TREATMENT)
# Confusion tables
datatable(cbind(t1),
caption = "Covariates Only")
datatable(cbind(t2),
caption = "PC1 Only")
datatable(cbind(t3),
caption = "PC1 with covariates")
datatable(cbind(t4),
caption = "PC1 + PC2 with covariates")
# Compare models
anova(m1, m3)
Likelihood ratio tests of Multinomial Models
Response: TREATMENT
Model Resid. df Resid. Dev Test Df LR stat. Pr(Chi)
1 WEEK + Genotype 204 199.6264
2 PC1 + WEEK + Genotype 201 155.9322 1 vs 2 3 43.69417 1.752679e-09
anova(m2, m3)
Likelihood ratio tests of Multinomial Models
Response: TREATMENT
Model Resid. df Resid. Dev Test Df LR stat. Pr(Chi)
1 PC1 210 169.3012
2 PC1 + WEEK + Genotype 201 155.9322 1 vs 2 9 13.36901 0.1466072
anova(m4, m3)
Likelihood ratio tests of Multinomial Models
Response: TREATMENT
Model Resid. df Resid. Dev Test Df LR stat. Pr(Chi)
1 PC1 + WEEK + Genotype 201 155.9322
2 PC1 + PC2 + WEEK + Genotype 198 152.3153 1 vs 2 3 3.616917 0.305912
The results suggest that:
a. Covariates alone (timepoint and genotype) cannot explain the difference between treatments.
b. Principal Component 1 (PC1) can explain the differences in relative abundance of classes in the samples. The model does not improve significantly by adding the covariates or the PC2. However, the covariates should stay in the model for adjustment, and PC2 slightly improves the predictions.
c. The full model (PC1 + PC2 + Week + Genotype) correctly classifies 12 out of 18 Naive samples, and 12 out of 18 DSS+Cranburry samples.
Continuing the same analysis at Order, Family and Genus levels.
DO ROC AUC NEST!!!
# # Output probobilities----
# prd1.1 <- predict(m1,
# type = "probs")
# prd1.1 <- data.table(ID = df.u$ID,
# Treatment = df.u$Treatment,
# round(prd1.1,
# 4))
#
# prd2.1 <- predict(m2,
# type = "probs")
# prd2.1 <- data.table(ID = df.u$ID,
# Treatment = df.u$Treatment,
# round(prd2.1,
# 4))
#
# # Sensitivity/Specificity
# # Tresholds
# trhd <- seq(0, 1, by = 0.01)
#
# out1 <- list()
# for (i in 1:length(trhd)) {
# tmp <- apply(prd1.1[, -c(1:2)],
# MARGIN = 2,
# FUN = function(a) {
# return(a >= trhd[i])
# })
# tmp2 <- apply(X = tmp,
# MARGIN = 2,
# FUN = function(a) {
# aggregate(x = a,
# by = list(prd1.1$Treatment),
# FUN = sum)$x
# })
# tmp2
# out1[[i]] <- c(sens = sum(diag(tmp2))/nrow(prd1.1),
# spec = (sum(tmp2[upper.tri(tmp2)]) +
# sum(tmp2[lower.tri(tmp2)]))/(nrow(tmp)*(ncol(tmp) - 1)))
# }
# out1 <- data.table(do.call("rbind", out1))
# out1 <- unique(out1)
#
# out2 <- list()
# for (i in 1:length(trhd)) {
# tmp <- apply(prd2.1[, -c(1:2)],
# MARGIN = 2,
# FUN = function(a) {
# return(a >= trhd[i])
# })
# tmp2 <- apply(X = tmp,
# MARGIN = 2,
# FUN = function(a) {
# aggregate(x = a,
# by = list(prd2.1$Treatment),
# FUN = sum)$x
# })
# out2[[i]] <- c(sens = sum(diag(tmp2))/nrow(prd2.1),
# spec = (sum(tmp2[upper.tri(tmp2)]) +
# sum(tmp2[lower.tri(tmp2)]))/(nrow(tmp)*(ncol(tmp) - 1)))
# }
# out2 <- data.table(do.call("rbind", out2))
# out2 <- unique(out2)
#
# # ROC
# roc1 <- auc(x = out1$spec,
# y = out1$sens,
# from = 0,
# to = 1)
#
# roc2 <- auc(x = out2$spec,
# y = out2$sens,
# from = 0,
# to = 1)
#
# # ROC plot
# plot(out1$sens ~ out1$spec,
# type = "l",
# xlim = c(0, 1),
# ylim = c(0, 1),
# xlab = "1 - Specificity",
# ylab = "Sensitivity",
# col = "blue")
# lines(out2$sens ~ out2$spec,
# col = "red")
# text(x = c(0.8, 0.8),
# y = c(0.2, 0.3),
# label = c(paste("ROC(PC1) = ",
# round(roc1,
# 3)),
# paste("\nROC(PC1+PC2) = ",
# round(roc2,
# 3))),
# col = c("blue",
# "red"))
# abline(0, 1, lty = 2)
mu$Trt_Genotype <- factor(paste(mu$Treatment,
mu$Genotype,
sep = "_"))
p0 <- ggplot(mu,
aes(x = Week,
y = x,
group = Trt_Genotype)) +
facet_wrap(~ Class,
scale = "free_y") +
geom_line(position = position_dodge(0.3)) +
geom_point(aes(fill = Trt_Genotype),
shape = 21,
size = 2,
alpha = 0.5,
position = position_dodge(0.3)) +
scale_x_discrete("") +
scale_y_continuous("Relative Abundance (%)") +
theme(legend.position = "top",
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/wt_class_over_time.tiff",
height = 5,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

p1 <- ggplot(mu,
aes(x = x,
y = Class,
color = Trt_Genotype,
shape = Week)) +
geom_point(size = 3,
alpha = 0.5) +
geom_vline(xintercept = 1,
linetype = "dashed") +
scale_x_continuous("Relative Abundance (%)")
tiff(filename = "tmp/wt_class_ra.tiff",
height = 4,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1+
theme(legend.position = "none"))
2. Order
mu$Trt_Genotype <- factor(paste(mu$Treatment,
mu$Genotype,
sep = "_"))
p0 <- ggplot(mu,
aes(x = Week,
y = x,
group = Trt_Genotype)) +
facet_wrap(~ Order,
scale = "free_y") +
geom_line(position = position_dodge(0.3)) +
geom_point(aes(fill = Trt_Genotype),
shape = 21,
size = 2,
alpha = 0.5,
position = position_dodge(0.3)) +
scale_x_discrete("") +
scale_y_continuous("Relative Abundance (%)") +
theme(legend.position = "top",
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/wt_Order_over_time.tiff",
height = 5,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0)
p1 <- ggplot(mu,
aes(x = x,
y = Order,
color = Trt_Genotype,
shape = Week)) +
geom_point(size = 3,
alpha = 0.5) +
geom_vline(xintercept = 1,
linetype = "dashed") +
scale_x_continuous("Relative Abundance (%)")
tiff(filename = "tmp/wt_Order_ra.tiff",
height = 4,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1 +
theme(legend.position = "none"))
3. Family
NOTE: only the first 24 families had large enough counts - ploting only them.
mu$Trt_Genotype <- factor(paste(mu$Treatment,
mu$Genotype,
sep = "_"))
mu1 <- droplevels(mu[Family %in% levels(mu$Family)[nlevels(mu$Family):(nlevels(mu$Family) - 24)], ])
p0 <- ggplot(mu1,
aes(x = Week,
y = x,
group = Trt_Genotype)) +
facet_wrap(~ Family,
scale = "free_y") +
geom_line(position = position_dodge(0.3)) +
geom_point(aes(fill = Trt_Genotype),
shape = 21,
size = 2,
alpha = 0.5,
position = position_dodge(0.3)) +
scale_x_discrete("") +
scale_y_continuous("Relative Abundance (%)") +
theme(legend.position = "top",
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/wt_Family_over_time.tiff",
height = 7,
width = 9,
units = "in",
res = 600,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0)
p1 <- ggplot(mu1,
aes(x = x,
y = Family,
color = Trt_Genotype,
shape = Week)) +
geom_point(size = 3,
alpha = 0.5) +
geom_vline(xintercept = 1,
linetype = "dashed") +
scale_x_continuous("Relative Abundance (%)") +
theme(legend.position = "top")
tiff(filename = "tmp/wt_Family_ra.tiff",
height = 4,
width = 7,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1+
theme(legend.position = "none"))
4. Genus
mu$Trt_Genotype <- factor(paste(mu$Treatment,
mu$Genotype,
sep = "_"))
mu1 <- droplevels(mu[Genus %in% levels(mu$Genus)[nlevels(mu$Genus):(nlevels(mu$Genus) - 35)], ])
p0 <- ggplot(mu1,
aes(x = Week,
y = x,
group = Trt_Genotype)) +
facet_wrap(~ Genus,
scale = "free_y") +
geom_line(position = position_dodge(0.3)) +
geom_point(aes(fill = Trt_Genotype),
shape = 21,
size = 2,
alpha = 0.5,
position = position_dodge(0.3)) +
scale_x_discrete("") +
scale_y_continuous("Relative Abundance (%)") +
theme(legend.position = "top",
axis.text.x = element_text(angle = 45,
hjust = 1))
tiff(filename = "tmp/wt_Genus_over_time.tiff",
height = 9,
width = 12,
units = "in",
res = 600,
compression = "lzw+p")
print(p0)
graphics.off()
print(p0+
theme(legend.position = "none"))
p1 <- ggplot(mu1,
aes(x = x,
y = Genus,
color = Trt_Genotype,
shape = Week)) +
geom_point(size = 3,
alpha = 0.5) +
geom_vline(xintercept = 1,
linetype = "dashed") +
scale_x_continuous("Relative Abundance (%)") +
theme(legend.position = "top")
tiff(filename = "tmp/wt_Genus_ra.tiff",
height = 9,
width = 9,
units = "in",
res = 600,
compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1+
theme(legend.position = "none"))
LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpemF0aW9uIG9mIFdUIGFuZCBOcmYyIEtPICgtLy0pIEJMNiBQRUlUQyBvciBDcmFuYmVycnkgVHJlYXRlZCBNaWNlIDE2UyBNaWNyb2Jpb21lIERhdGEgQW5hbHlzaXMsIFNlcHRlbWJlciAyMDE5IEJhdGNoIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9CiMgb3B0aW9ucyhzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiMgICAgICAgICBzY2lwZW4gPSA5OTkpCgojICMgSW5jcmVhc2UgbW1lbW9yeSBzaXplIHRvIDY0IEdiLS0tLQojIGludmlzaWJsZSh1dGlsczo6bWVtb3J5LmxpbWl0KDY1NTM2KSkKCgojIHN0cihrbml0cjo6b3B0c19jaHVuayRnZXQoKSkKIyAjIE5PVEU6IHRoZSBiZWxvdyBkb2VzIG5vdCB3b3JrIQojIGtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsIAojICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsCiMgICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBGQUxTRSkKCiMgcmVxdWlyZShrbml0cikKIyByZXF1aXJlKGthYmxlRXh0cmEpCiMgcmVxdWlyZShzaGlueSkKCnJlcXVpcmUocGh5bG9zZXEpCnJlcXVpcmUoZGF0YS50YWJsZSkKcmVxdWlyZShnZ3Bsb3QyKQpyZXF1aXJlKHBsb3RseSkKcmVxdWlyZShEVCkKcmVxdWlyZShsbWVyVGVzdCkKcmVxdWlyZShubmV0KQoKc291cmNlKCJzb3VyY2UvZnVuY3Rpb25zX21heTIwMTkuUiIpCgojIE9uIFdpbmRvd3Mgc2V0IG11bHRpdGhyZWFkPUZBTFNFLS0tLQptdCA8LSBUUlVFCmBgYAoKIyBJbnRyb2R1Y3Rpb24KQzU3QkwvNiB3aWxkLXR5cGUgKFdUKSBhbmQgTnJmLTIgZG91YmxlLWtub2NrLW91dCAoS08gLS8tKSBtaWNlIHdlcmUgZ2l2ZW4gMi13ZWVrIG1pY3JvYmlvbWUgc3RhYmlsaXphdGlvbiBwcm9jZXNzIHVzaW5nIEFJTjkzTSBkaWV0IGFuZCA4IG1vcmUgd2Vla3MgdG8gdHJlYXQgd2l0aCBlaXRoZXIgQUlOOTNNIG9yIEFJTjkzTSA1JSBQRUlUQyBkaWV0LiBGZWNhbCBzYW1wbGVzIHdlcmUgY29sbGVjdGVkIHdlZWtseSwgaW1tZWRpYXRlbHkgZnJvemVuIGluIGxpcXVpZCBuaXRyb2dlbiBhbmQgc3RvcmVkIGF0IC04MF5vXkMuIFNlcnVtLCBjZWNhbCwgY29sb24gZXBpdGhlbGlhbCBhbmQgd2hvbGUgY29sb24gdGlzc3VlcyBhdCB3ZWVrIDEwIHdlcmUgYWxzbyBjb2xsZWN0ZWQgZm9yIGZ1cnRoZXIgYW5hbHlzZXMuIEJhc2VsaW5lLCB3ZWVrIDEgYW5kIDQgZmVjYWwgc2FtcGxlcyB3ZXJlIHNlbGVjdGVkIGZvciAxNnMgclJOQSBzZXF1ZW5jaW5nLiAgCiAgClRoaXMgZG9jdW1lbnQgZXhhbWluZXMgcmVzdWx0cyBmcm9tIHRoZSBXVCBtaWNlIHNhbXBsZXMuICAKICAKV2Ugd2lsbCBhdHRhbXB0IHRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczogIAoxLiBEaWQgbWljcm9iaW9tZSBjaGFuZ2Ugb3ZlciB0aW1lPyAgCjIuIFdhcyBtaWNyb2Jpb21lIGFmZmVjdGVkIGJ5IGRpZXQ/ICAKMy4gV2FzIHRoZXJlIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBLTyBhbmQgV1Q/ICAKNC4gSWYgdGhlcmUgd2FzIGEgY2hhbmdlIGluIG1pY3JvYmlvbWUgY29tcG9zaXRpb24sIHdoYXQgZnVuY3Rpb25hbCBjaGFuZ2VzIGRpZCBpdCBjYXJyeT8gV2hhdCBhcmUgdGhlIGVzc2VudGlhbCBmdW5jdGlvbnMgb2YgdGhlIGJhY3RlcmlhIGFmZmVjdGVkIGJ5IHRoZSB0cmVhdG1lbnQgYW5kIGhvdyBjYW4gdGhpcyBiZSBzaG93biBpbiB2aXZvIChtZXRhYm9saXRlcywgaW5mbGFtbWF0aW9uIG1hcmtlcnMsIGV0Yy4pPwoKIyBEYXRhIHByZXByb2Nlc3NpbmcKIyMgUmF3IERhdGEgCkZhc3RRIGZpbGVzIHdlcmUgZG93bmxvYWRlZCBmcm9tIFt0aGlzIFJ1dGdlcnMgQm94IGxvY2F0aW9uXShodHRwczovL3J1dGdlcnMuYXBwLmJveC5jb20vZm9sZGVyLzkwMTQzNDYyMjkxKS4gQSB0b3RhbCBvZiAxNDQgZmlsZXMgKDIgcGVyIHNhbXBsZSwgcGFpci1lbmRlZCkgYW5kIGEgcGFpciBvZiB1bmRldGVybWluZWQgcmVhZHMgd2VyZSBkb3dubG9hZGVkLiAKCiMjIFNjcmlwdApUaGlzIHNjcmlwdCAoKioqbnJmMnViaW9tZV9kYWRhMl9zZXAyMDE5X3YxLlJtZCoqKikgd2FzIGRldmVsb3BlZCB1c2luZyBbREFEQTIgUGlwZWxpbmUgVHV0b3JpYWwgKDEuMTIpXShodHRwczovL2JlbmpqbmViLmdpdGh1Yi5pby9kYWRhMi90dXRvcmlhbC5odG1sKSB3aXRoIHRpcHMgYW5kIHRyaWNrcyBmcm9tIHRoZSBbVW5pdmVyc2l0eSBvZiBNYXJ5bGFuZCBTaG9vbCBvZiBNZWRpY2luZSBJbnN0aXR1dGUgZm9yIEdlbm9tZSBTY2llbmNlcyAoSUdTKV0oaHR0cDovL3d3dy5pZ3MudW1hcnlsYW5kLmVkdS8pIFtNaWNyb2Jpb21lIEFuYWx5c2lzIFdvcmtzaG9wIChBcHJpbCA4LTExLCAyMDE5KV0oaHR0cDovL3d3dy5pZ3MudW1hcnlsYW5kLmVkdS9lZHVjYXRpb24vd2tzaHBfbWV0YWdlbm9tZS5waHApLiBUaGUgb3V0cHV0IG9mIHRoZSBEQURBMiBzY3JpcHQgKCoqKmRhdGFfbWF5MjAxOS9wc19zZXAyMDE5LlJEYXRhKioqKSBpcyBleHBsb3JlZCBpbiB0aGlzIGRvY3VtZW50LgoKIyBNZXRhIGRhdGE6IHNhbXBsZSBkZXNjcmlwdGlvbgpgYGB7ciBkYXRhfQojIExvYWQgZGF0YS0tLS0KIyBDb3VudHMKbG9hZCgiZGF0YV9zZXAyMDE5L3BzX3NlcDIwMTkuUkRhdGEiKQoKIyBUYXhvbm9teQpsb2FkKCJkYXRhX3NlcDIwMTkvdGF4YS5SRGF0YSIpCnRheGEgPC0gZGF0YS50YWJsZShzZXExNnMgPSByb3duYW1lcyh0YXhhKSwKICAgICAgICAgICAgICAgICAgIHRheGEpCmBgYAoKKipOT1RFOiBjb3JyZWN0aW9uIHRvIHRoZSBtZXRhLWRhdGEhKiogKDExLzE1LzIwMTkpCmBgYHtyIGNvcnJlY3RfbWV0YV9kYXRhfQpjb3JyZWN0X3NhbXBsZXMgPC0gZnJlYWQoImRhdGFfc2VwMjAxOS8xNnMgbWV0YWRhdGEgU2VwLTIwMTkuY3N2IikKcHNfc2VwMjAxOUBzYW1fZGF0YSREU1MgPC0gY29ycmVjdF9zYW1wbGVzJERTUwpgYGAKCiMgU2FtcGxlcwpgYGB7ciBzYW1wbGVzfQpwc19zZXAyMDE5QHNhbV9kYXRhJEdlbm90eXBlX1dlZWsgPC0gcGFzdGUocHNfc2VwMjAxOUBzYW1fZGF0YSRnZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzX3NlcDIwMTlAc2FtX2RhdGEkdGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikKcHNfc2VwMjAxOUBzYW1fZGF0YSRJRCA8LSBmYWN0b3IocGFzdGUwKHBzX3NlcDIwMTlAc2FtX2RhdGEkbWljZV9udW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwc19zZXAyMDE5QHNhbV9kYXRhJGNhZ2UpKQoKcHNfc2VwMjAxOUBzYW1fZGF0YSRUUkVBVE1FTlQgPC0gcGFzdGUwKHBzX3NlcDIwMTlAc2FtX2RhdGEkRFNTLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHNfc2VwMjAxOUBzYW1fZGF0YSRQRUlUQywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzX3NlcDIwMTlAc2FtX2RhdGEkY3JhbmJlcnJ5KQpwc19zZXAyMDE5QHNhbV9kYXRhJFRSRUFUTUVOVCA8LSBmYWN0b3IocHNfc2VwMjAxOUBzYW1fZGF0YSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIwMDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjExMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxMDEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk5haXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MrUEVJVEMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTK0NyYW5iZXJyeSIpKQoKc2FtcGxlcyA8LSBwc19zZXAyMDE5QHNhbV9kYXRhCmRhdGF0YWJsZShzYW1wbGVzLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IG5yb3coc2FtcGxlcykpKQpgYGAKCiMgUHJ1bmUgZGF0YQpUaGUgT1RVcyB3ZXJlIG1hcHBlZCB0byBCYWN0ZXJpYSAoOTYuMDclKSwgRXVrYXJ5b3RhICgyLjk1JSkgYW5kIEFyY2hlYSAoMC4wMyUpIGtpbmdkb21zLCBhbmQgIDc1IE9UVXMgKDAuOTUlKSB1bmRlZmluZWQuIAoKYGBge3IgY2hlY2tfbWFwcGluZ19raW5nZG9tLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQp0MSA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwc19zZXAyMDE5KVssICJLaW5nZG9tIl0sCiAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MSRWMVtpcy5uYSh0MSRWMSldIDwtICJVbmtub3duIgoKdDFbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQxLCAtTikKCmNvbG5hbWVzKHQxKSA8LSBjKCJLaW5nZG9tIiwKICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIiwKICAgICAgICAgICAgICAgICAgIlBlcmNlbnQgb2YgT1RVcyIpCmRhdGF0YWJsZSh0MSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBPVFVzIGJ5IEtpbmdkb20iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDEpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKClRoZSB0b3RhbCBvZiA3LDg2NyB1bmlxdWUgc2VxdWVuY2VzIHdlcmUgZm91bmQuIE91dCBvZiB0aG9zZSwgNyw1NTggd2VyZSBtYXBwZWQgdG8gYmFjdGVyaWFsIGdlbm9tZXMuIAoKYGBge3Iga2VlcF9iYWN0ZXJpYX0KZGltKHBzX3NlcDIwMTlAb3R1X3RhYmxlQC5EYXRhKQoKIyBSZW1vdmUgT1RVIG5vdCBtYXBwZWQgdG8gQmFjdGVyaWEKcHMwIDwtIHN1YnNldF90YXhhKHBzX3NlcDIwMTksIAogICAgICAgICAgICAgICAgICAgS2luZ2RvbSA9PSAiQmFjdGVyaWEiKQpkaW0ocHMwQG90dV90YWJsZUAuRGF0YSkKYGBgCiAgCk91dCBvZiB0aGUgNyw1NTggT1RVcyA3LDI0NyBiZWxvbmdlZCB0byAxMiBQaHlsYS4gMzExIG9mIHRoZSBPVFVzIChvciA0LjExJSBvZiBiYWN0ZXJpYWwgT1RVcykgY291bGQgbm90IGJlIG1hcHBlZCB0byBhIHBoeWx1bS4KCmBgYHtyIHBoeWx1bV9tYXBwaW5nfQp0MiA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwczApWywgIlBoeWx1bSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MiRWMVtpcy5uYSh0MiRWMSldIDwtICJVbmtub3duIgpzZXRvcmRlcih0MiwgLU4pCnQyWywgcGN0IDo9IE4vc3VtKE4pXQpzZXRvcmRlcih0MiwgLU4pCgpjb2xuYW1lcyh0MikgPC0gYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIiwKICAgICAgICAgICAgICAgICAgIlBlcmNlbnQgb2YgT1RVcyIpCgpkYXRhdGFibGUodDIsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJOdW1iZXIgb2YgQmFjdGVyaWFsIE9UVXMgYnkgUGh5bHVtIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHQyKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgojIE9UVSB0YWJsZSAoZmlyc3QgMTAgcm93cykKYGBge3Igb3R1X3RhYmxlLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0Kb3R1IDwtIGRhdGEudGFibGUocHMwQHRheF90YWJsZUAuRGF0YSwKICAgICAgICAgICAgICAgICAgdChwczBAb3R1X3RhYmxlQC5EYXRhKSkKZGF0YXRhYmxlKGhlYWQob3R1LCAxMCksCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA3OjM2LAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMgVG90YWwgY291bnRzIHBlciBzYW1wbGUgKGkuZS4gc2VxdWVuY2luZyBkZXB0aCkKYGBge3Igc2VxX2RlcHRoLCBmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gNX0KdDEgPC0gY29sU3VtcyhvdHVbLCA3Om5jb2wob3R1KV0pCnQxIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBuYW1lcyh0MSksCiAgICAgICAgICAgICAgICAgVG90YWwgPSB0MSkKCnQyIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSByb3duYW1lcyhzYW1wbGVzKSwKICAgICAgICAgICAgICAgICBJRCA9IHNhbXBsZXMkSUQsCiAgICAgICAgICAgICAgICAgQ0FHRSA9IHNhbXBsZXMkY2FnZSwKICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzYW1wbGVzJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IHNhbXBsZXMkZ2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgV0VFSyA9IHNhbXBsZXMkdGltZSkKCnNtcGwgPC0gbWVyZ2UodDEsCiAgICAgICAgICAgICAgdDIsCiAgICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKcDEgPC0gZ2dwbG90KHNtcGwsCiAgICAgICAgICAgICBhZXMoeCA9IFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgIHkgPSBUb3RhbCwKICAgICAgICAgICAgICAgICBmaWxsID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIGNvbG91ciA9IFdFRUspKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV94IikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiTnVtYmVyIG9mIFJlYWRzIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUoIlRyZWF0bWVudCIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpIApnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBzZXFfZGVwdGhfZ3JleXNjYWxlLCAsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2fQp0bXAgPC0gY29weShzbXBsKQp0bXAkV0VFSyA8LSBmYWN0b3IodG1wJFdFRUssCiAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYmFzZWxpbmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWsxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3ZWVrOCIpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIldlZWsgMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXZWVrIDgiKSkKdG1wJEdlbm90eXBlIDwtIGZhY3Rvcih0bXAkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygid2lkZXR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5yZjJLTyIpLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIldpbGQgVHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTnJmMiBLTyIpKQpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgZmlsbCA9IFRSRUFUTUVOVCkpICsKICBmYWNldF93cmFwKH4gR2Vub3R5cGUgKyBXRUVLLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV94IikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIk51bWJlciBvZiBSZWFkcyIpICsKICBzY2FsZV9maWxsX2dyZXkoIlRyZWF0bWVudCIsIAogICAgICAgICAgICAgICAgICBzdGFydCA9IDAuMSwgCiAgICAgICAgICAgICAgICAgIGVuZCA9IDEsCiAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInJlZCIsCiAgICAgICAgICAgICAgICAgIGFlc3RoZXRpY3MgPSAiZmlsbCIpICsKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC9zZXFfZGVwdGgudGlmZiIsCiAgICAgaGVpZ2h0ID0gNiwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDEpCmBgYAoKIyBSaWNobmVzcyAoQWxwaGEgZGl2ZXJzaXR5KQpTaGFubm9uIGluZGV4IChha2EgU2hhbm5vbiBlbnRocm9waHkpIGlzIGNhbGN1bGF0ZWQgYXM6ICAKSCcgPSAtc3VtKDEgdG8gUilwKGkpbG4ocChpKSkgCldoZW4gdGhlcmUgaXMgZXhhY3RseSAxIHR5cGUgb2YgZGF0YSAoZS5nLiBhIHNpbmdsZSBzcGVjaWVzIGluIHRoZSBzYW1wbGUpLCBIJz0wLiBUaGUgb3Bwb3NpdGUgc2NlbmFyaW8gaXMgd2hlbiB0aGVyZSBhcmUgUj4xIHNwZWNpZXMgcHJlc2VudCBpbiB0aGUgc2FtcGxlIGluIHRoZSBleGFjdCBzYW1lIGFtb3VudHMgYW5kIEgnPWxuKFIpLiAgCiAgClNoYW5ub24ncyBkaXZlcnNpdHkgaW5kZXggd2FzIGNhbGN1bGF0ZWQgZm9yIGVhY2ggc2FtcGxlIGFuZCBwbG90ZWQgb3ZlciB0aW1lIHVzaW5nIHRoZSA3LDc2NCBmcm9tIHRoZSAxMyBQaHlsdW0gYWJvdmUuCiAgCmBgYHtyIHNoYW5ub25fdnNfZGVwdGgsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA2fQpzaGFubm9uLm5keCA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwczAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmVzID0gIlNoYW5ub24iKQoKc2hhbm5vbi5uZHggPC0gZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHJvd25hbWVzKHNoYW5ub24ubmR4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzaGFubm9uLm5keCkKCnNtcGwgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICBzaGFubm9uLm5keCwKICAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgpwMSA8LSBnZ3Bsb3Qoc21wbCwKICAgICAgICAgICAgIGFlcyh4ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgeSA9IFNoYW5ub24sCiAgICAgICAgICAgICAgICAgZmlsbCA9IEdlbm90eXBlLAogICAgICAgICAgICAgICAgIHNoYXBlID0gV0VFSykpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKGJyZWFrcyA9IHVuaXF1ZShzbXBsJFdFRUspLAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSAyMToyMykKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3NoYW5ub25fdnNfZGVwdGgudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDEpCmBgYAoKRXZlbiB0aG91Z2ggKioqZXN0aW1hdGVfcmljaG5lc3MqKiogZnVuY3Rpb24gZG9lcyBub3QgYWRqdXN0IGZvciB0aGUgc2VxdWVuY2luZyBkZXB0aCwgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgaW5kZXggYW5kIHRoZSBzYW1wbGUncyBzZXF1ZWNpbmcgZGVwdGguIFByb2NlZWQgd2l0aCB0aGUgY29tcGFyaXNvbi4KCiMgU2hhbm5vbiBpZGV4IG92ZXIgdGltZQpgYGB7ciByaWNobmVzcywgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDV9CnAxIDwtIHBsb3RfcmljaG5lc3MocHMwLAogICAgICAgICAgICAgICAgICAgIHggPSAidGltZSIsIAogICAgICAgICAgICAgICAgICAgIG1lYXN1cmVzID0gIlNoYW5ub24iKSArCiAgZmFjZXRfd3JhcCh+IGdlbm90eXBlKSArCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IElEKSwKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFRSRUFUTUVOVCksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAxKSkKCmdncGxvdGx5KHAgPSBwMSwKICAgICAgICAgdG9vbHRpcCA9IGMoIklEIiwKICAgICAgICAgICAgICAgICAgICAgInZhbHVlIikpCgpwMSA8LSBwMSArIAogIHNjYWxlX2ZpbGxfZGlzY3JldGUoIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3NoYW5ub24udGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDUsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQpgYGAKClRoZSBwbG90IGFib3ZlIHN1Z2dlc3RzIHRoYXQgdGhlIGxhcmdlc3QgZGlmZmVyZW5jZXMgaW4gYWxwaGEgZGl2ZXJzaXR5IChhcyBtZWFzdXJlZCBieSBTaGFubm9uJ3MgaW5kZXgpIGFyZSBpbiBnZW5vdHlwZS4KCiMgQXZlcmFnZSBTaGFubm9uIEluZGV4CmBgYHtyIGF2Z19zaGFubm9uX3Bsb3QsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA1fQojIEF2ZXJhZ2Ugc2hhbm5vbiBpbmRleCBieSB0cmVhdG1lbnQgZ3JvdXAKdG1wIDwtIGNvcHkoc21wbCkKCnRtcFssIG11IDo9IG1lYW4oU2hhbm5vbiksCiAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgIEdlbm90eXBlLAogICAgICAgICAgICAgIFdFRUspXQp0bXBbLCBzZW0gOj0gc2QoU2hhbm5vbikvc3FydCguTiksCiAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIEdlbm90eXBlLAogICAgICAgICAgICAgICAgIFdFRUspXQp0bXAgPC0gdW5pcXVlKHRtcFssIGMoIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAiR2Vub3R5cGUiLAogICAgICAgICAgICAgICAgICAgICAgIldFRUsiLAogICAgICAgICAgICAgICAgICAgICAgIm11IiwKICAgICAgICAgICAgICAgICAgICAgICJzZW0iKV0pCnRtcCRXRUVLIDwtIGZhY3Rvcih0bXAkV0VFSywKICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJhc2VsaW5lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWsxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWs4IiksCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJXZWVrIDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldlZWsgOCIpKQp0bXAkR2Vub3R5cGUgPC0gZmFjdG9yKHRtcCRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJ3aWRldHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibnJmMktPIiksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiV2lsZCBUeXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOcmYyIEtPIikpCgpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBXRUVLLAogICAgICAgICAgICAgICAgIHkgPSBtdSwKICAgICAgICAgICAgICAgICB5bWluID0gbXUgLSBzZW0sCiAgICAgICAgICAgICAgICAgeW1heCA9IG11ICsgc2VtLAogICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUUkVBVE1FTlQpKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlKSArCiAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCksCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuNCkgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC40KSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlNoYW5ub24gSW5kZXgiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKCnRpZmYoZmlsZW5hbWUgPSAidG1wL2F2Z19zaGFubm9uLnRpZmYiLAogICAgIGhlaWdodCA9IDUsCiAgICAgd2lkdGggPSA2LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAxKQpgYGAKICAKVGVzdCBpZiB0aGUgcmljaG5lc3MgY2hhbmdlZCBiZXR3ZWVuIHRoZSBiYXNlbGluZSBhbmQgV2VlayA4LiAgCiAgCmBgYHtyIGxtX3JpY2huZXNzfQpzbXBsJFRSRUFUTUVOVCA8LSBmYWN0b3Ioc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEU1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTK1BFSVRDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnkiKSkKCnRtcCA8LSBkcm9wbGV2ZWxzKHNtcGxbV0VFSyAhPSAid2VlazEiXSkKCm0xIDwtIGxtKFNoYW5ub24gIH4gV0VFSyooVFJFQVRNRU5UICsgR2Vub3R5cGUpLAogICAgICAgICAjIG9mZnNldCA9IFRvdGFsLAogICAgICAgICBkYXRhID0gdG1wKQpzdW1tYXJ5KG0xKQpgYGAKICAKYGBge3IgbG1lcl9yaWNobmVzc30KbTIgPC0gbG1lcihTaGFubm9uICB+IFdFRUsqKFRSRUFUTUVOVCArIEdlbm90eXBlKSArICgxIHwgSUQpLAogICAgICAgICAgICMgb2Zmc2V0ID0gVG90YWwsCiAgICAgICAgICAgZGF0YSA9IHRtcCkKc3VtbWFyeShtMikKYGBgCgojIENhbGN1bGF0ZSBjaGFuZ2UgaW4gU2hhbm5vbiBpbmRleCBmcm9tIGJhc2VsaW5lCmBgYHtyIGRlbHRhX3NoYW5ub24sIGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA1fQpkZCA8LSBzbXBsCmRkWywgZGVsdGEgOj0gU2hhbm5vbiAtIFNoYW5ub25bV0VFSyA9PSAiYmFzZWxpbmUiXSwKICAgYnkgPSBJRF0KZGQkZGlmZiA8LSBwYXN0ZShkZCRXRUVLLAogICAgICAgICAgICAgICAgICItYmFzZWxpbmUiLAogICAgICAgICAgICAgICAgIHNlcCA9ICIiKQoKZGQgPC0gZGRbV0VFSyAhPSAiYmFzZWxpbmUiLF0KCnAxIDwtIGdncGxvdChkZCwKICAgICAgICAgICAgIGFlcyh4ID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIHkgPSBkZWx0YSwKICAgICAgICAgICAgICAgICBmaWxsID0gR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IGRpZmYpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLAogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJTaGFubm9uIEluZGV4IFBlcmNlbnQgQ2hhbmdlIGZyb20gQmFzZWxpbmUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQpwcmludChwMSkKCmRkJFRSRUFUTUVOVCA8LSBmYWN0b3IoZGQkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEU1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOYWl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytQRUlUQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnkiKSkKZGQkR2Vub3R5cGUgPC0gZmFjdG9yKGRkJEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIndpZGV0eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJucmYyS08iKSkKCm0xIDwtIGxtKGRlbHRhIH4gVFJFQVRNRU5UKkdlbm90eXBlLAogICAgICAgICBkYXRhID0gZGQpCnN1bW1hcnkobTEpCgojIE5vIHNpZ25pZmljYW50IGludGVyYWN0aW9ucywgcHJvY2VlZCB3aXRoIDItd2F5IGFuYWx5c2lzCm0yIDwtIGxtKGRlbHRhIH4gVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgIGRhdGEgPSBkZCkKc3VtbWFyeShtMikKYGBgCgpBdCBXZWVrIDggdGhlcmUgd2FzIHNpZ25pZmljYW50bHkgc21hbGxlciBpbmNyZWFzZSBvZiBhbHBoYSBkaXZlcnNpdHkgZnJvbSBiYXNlbGluZSBpbiBOcmYyIEtPIGNvbXBhcmVkIHRvIFdULCBhbmQgaW4gRFNTK0NyYW5iZXJyeSBjb21wYXJlZCB0byBEU1Mgb25seS4KCiMgTG9hZCBhbWlub2FjaWRzCmBgYHtyIGFtaW5vYWNpZHNfZGF0YX0KYWEgPC0gZnJlYWQoImRhdGFfc2VwMjAxOS9zZXAyMDE5X2FtaW5vYWNpZHMuY3N2IikKCmFhIDwtIGFhWyFpcy5uYShJRCksIF0KYWEkSUQgPC0gcGFzdGUwKGFhJElELAogICAgICAgICAgICAgICAgYWEkQ0FHRSkKCnNtcGwxIDwtIHVuaXF1ZShzbXBsWywgYygiSUQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR2Vub3R5cGUiKV0pCnNtcGwxJElEIDwtIGFzLmNoYXJhY3RlcihzbXBsMSRJRCkKYWEgPC0gbWVyZ2Uoc21wbDEsCiAgICAgICAgICAgIGFhLAogICAgICAgICAgICBieSA9ICJJRCIpCmFhWywgdHJ0X3dlZWsgOj0gcGFzdGUoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgIFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIl8iKV0KYWEkdHJ0X3dlZWsgPC0gZmFjdG9yKGFhJHRydF93ZWVrLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTmFpdmVfd2VlazIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFpdmVfd2VlazYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTX3dlZWsyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTU193ZWVrNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MrQ3JhbmJlcnJ5X3dlZWsyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnlfd2VlazYiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytQRUlUQ193ZWVrMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MrUEVJVENfd2VlazYiKSkKYGBgCgojIEFtaW5vYWNpZHMgYnkgYW5pbWFsLCB0cmVhdG1lbnQgZ3JvdXAgYW5kIHRpbWVwb2ludApgYGB7ciBhbWlub2FjaWRzX3Bsb3RzLCBmaWcuaGVpZ2h0ID0gNCwgZmlnLndpZHRoID0gNX0KZm9yIChpIGluIDg6KG5jb2woYWEpIC0gMSkpIHsKICB0bXAgPC0gYWFbLCBjKDEsIDMsIDcsIG5jb2woYWEpLCBpKSwgd2l0aCA9IEZBTFNFXQogIGNvbG5hbWVzKHRtcClbNV0gPC0gIlkiCiAgcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgICAgYWVzKHggPSB0cnRfd2VlaywKICAgICAgICAgICAgICAgICAgIHkgPSBZLAogICAgICAgICAgICAgICAgICAgZmlsbCA9IEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBJRCkpICsKICAgIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwKICAgICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogICAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGNvbG5hbWVzKGFhKVtpXSkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCiAgIyB0aWZmKGZpbGVuYW1lID0gcGFzdGUwKCJ0bXAvIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgY29sbmFtZXMoYWEpW2ldLAogICMgICAgICAgICAgICAgICAgICAgICAgICAiLnRpZmYiKSwKICAjICAgICAgaGVpZ2h0ID0gNCwKICAjICAgICAgd2lkdGggPSA1LAogICMgICAgICB1bml0cyA9ICJpbiIsCiAgIyAgICAgIHJlcyA9IDYwMCwKICAjICAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQogICMgcHJpbnQocDEpCiAgIyBncmFwaGljcy5vZmYoKQogIAogIHByaW50KHAxKQp9CmBgYAoKIyBBbWlub2FjaWRzIG92ZXIgdGltZSwgZ3JvdXAgYXZlcmFnZXMKYGBge3IgYW1pbm9hY2lkc19hdmdfcGxvdHMsIGZpZy5oZWlnaHQgPSA0LCBmaWcud2lkdGggPSA1fQpvdXQgPC0gbGlzdCgpCmZvciAoaSBpbiA4OjI3KSB7CiAgdG1wIDwtIGFhWywgYygyLCAzLCA3LCBpKSwgCiAgICAgICAgICAgIHdpdGggPSBGQUxTRV0KICBuYW1lcyh0bXApWzRdIDwtICJ2YWwiCiAgCiAgdG1wWywgbXUgOj0gbWVhbih2YWwsCiAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpLAogICAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgR2Vub3R5cGUsCiAgICAgICAgICAgICAgICBXRUVLKV0KICB0bXBbLCBzZW0gOj0gc2QodmFsLAogICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpL3NxcnQoLk4pLAogICAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgR2Vub3R5cGUsCiAgICAgICAgICAgICAgICBXRUVLKV0KICBvdXRbW2kgLSA3XV0gPC0gZGF0YS50YWJsZShBbWlub2FjaWQgPSBuYW1lcyhhYSlbaV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pcXVlKHRtcFssIGMoIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0VFSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm11IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2VtIildKSkKfQptdWFhIDwtIHJiaW5kbGlzdChvdXQpCm11YWEkQW1pbm9hY2lkIDwtIGZhY3RvcihtdWFhJEFtaW5vYWNpZCwKICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShtdWFhJEFtaW5vYWNpZCkpCm11YWEkR2Vub3R5cGUgPC0gZmFjdG9yKG11YWEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIndpZGV0eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibnJmMktPIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIldpbGQgVHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5yZjIgS08iKSkKCmZvciAoaSBpbiAxOm5sZXZlbHMobXVhYSRBbWlub2FjaWQpKSB7CiAgcDEgPC0gZ2dwbG90KG11YWFbQW1pbm9hY2lkID09IGxldmVscyhtdWFhJEFtaW5vYWNpZClbaV0sIF0sCiAgICAgICAgICAgICAgIGFlcyh4ID0gV0VFSywKICAgICAgICAgICAgICAgICAgIHkgPSBtdSwKICAgICAgICAgICAgICAgICAgIHltaW4gPSBtdSAtIHNlbSwKICAgICAgICAgICAgICAgICAgIHltYXggPSBtdSArIHNlbSwKICAgICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICBncm91cCA9IFRSRUFUTUVOVCkpICsKICAgIGZhY2V0X3dyYXAofiBHZW5vdHlwZSkgKwogICAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCksCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC40KSArCiAgICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjQpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCkpICsKICAgIHNjYWxlX3hfZGlzY3JldGUoIiIsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoIndlZWsyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VlazYiKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiV2VlayAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayA2IikpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsZXZlbHMobXVhYSRBbWlub2FjaWQpW2ldKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKICAKICAjIHRpZmYoZmlsZW5hbWUgPSBwYXN0ZTAoInRtcC9hdmdfIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzKG11YWEkQW1pbm9hY2lkKVtpXSwKICAjICAgICAgICAgICAgICAgICAgICAgICAgIi50aWZmIiksCiAgIyAgICAgIGhlaWdodCA9IDUsCiAgIyAgICAgIHdpZHRoID0gNiwKICAjICAgICAgdW5pdHMgPSAiaW4iLAogICMgICAgICByZXMgPSA2MDAsCiAgIyAgICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKICAjIHByaW50KHAxKQogICMgZ3JhcGhpY3Mub2ZmKCkKICAKICBwcmludChwMSkKfQpgYGAKCiMgQW1pbm9hY2lkIGRhdGEgUENBCmBgYHtyIGFtaW5vYWNpZHNfcGNhfQpkdF9wY2EgPC0gYWFbLCBBbGFuaW5lOmdsdXRhbWluZV0KCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gRkFMU0UsCiMgICAgICAgICAgICAgIHNjYWxlLiA9IEZBTFNFKQoKbTEgPC0gcHJjb21wKGR0X3BjYSkKCnN1bW1hcnkobTEpCgoKIyBTZWxlY3QgUEMtcyB0byBwbGlvdCAoUEMxICYgUEMyKQpjaG9pY2VzIDwtIDE6MgojIFNjb3JlcywgaS5lLiBwb2ludHMgKGRmLnUpCmR0LnNjciA8LSBkYXRhLnRhYmxlKG0xJHhbLCBjaG9pY2VzXSkKIyBBZGQgZ3JvdXBpbmcgdmFyaWFibGUKZHQuc2NyJGdycCA8LSBhYSR0cnRfd2VlawpkdC5zY3IkVFJFQVRNRU5UIDwtIGFhJFRSRUFUTUVOVApkdC5zY3IkV0VFSyA8LSBhYSRXRUVLCmR0LnNjcgoKIyBMb2FkaW5ncywgaS5lLiBhcnJvd3MgKGRmLnYpCmR0LnJvdCA8LSBhcy5kYXRhLmZyYW1lKG0xJHJvdGF0aW9uWywgY2hvaWNlc10pCmR0LnJvdCRmZWF0IDwtIHJvd25hbWVzKGR0LnJvdCkKZHQucm90IDwtIGRhdGEudGFibGUoZHQucm90KQpkdC5yb3QKCmR0LmxvYWQgPC0gbWVsdC5kYXRhLnRhYmxlKGR0LnJvdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9ICJmZWF0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gInBjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJsb2FkaW5nIikKZHQubG9hZCRmZWF0IDwtIGZhY3RvcihkdC5sb2FkJGZlYXQsCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKGR0LmxvYWQkZmVhdCkpCiMgUGxvdCBsb2FkaW5ncwpwMCA8LSBnZ3Bsb3QoZGF0YSA9IGR0LmxvYWQsCiAgICAgICAgICAgICBhZXMoeCA9IGZlYXQsCiAgICAgICAgICAgICAgICAgeSA9IGxvYWRpbmcpKSArCiAgZmFjZXRfd3JhcCh+IHBjLAogICAgICAgICAgICAgbnJvdyA9IDIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBDIExvYWRpbmdzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvcGMuMS4yX2xvYWRpbmdzLnRpZmYiLAogICAgIGhlaWdodCA9IDUsCiAgICAgd2lkdGggPSA4LAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMCkKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAwKQpgYGAKCmBgYHtyIGFtaW5vYWNpZHNfcGNhX2F4ZXN9CiMgQXhpcyBsYWJlbHMKdS5heGlzLmxhYnMgPC0gcGFzdGUoY29sbmFtZXMoZHQucm90KVsxOjJdLCAKICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZignKCUwLjFmJSUgZXhwbGFpbmVkIHZhci4pJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAwKm0xJHNkZXZbY2hvaWNlc11eMi9zdW0obTEkc2Rldl4yKSkpCnUuYXhpcy5sYWJzCmBgYAoKYGBge3IgYW1pbm9hY2lkc19iaXBsb3QsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gZ3JwKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDEwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAxMCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgICMgc2l6ZSA9IDEsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSAxMSpQQzEsCiAgICAgICAgICAgICAgICB5ID0gMTEqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkdyb3VwIikgKwogIGdndGl0bGUoIkJpcGxvdCBvZiBBbWlub2FjaWRzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMjApKQp0aWZmKGZpbGVuYW1lID0gInRtcC9hbWlub2FjaWRzX2JpcGxvdC50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIGFtaW5vYWNpZHNfYmlwbG90X2J5X3dlZWssIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CnAyIDwtIGdncGxvdChkYXRhID0gZHQucm90LAogICAgICAgICAgICAgYWVzKHggPSBQQzEsCiAgICAgICAgICAgICAgICAgeSA9IFBDMikpICsKICBjb29yZF9lcXVhbCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkdC5zY3IsCiAgICAgICAgICAgICBhZXMoZmlsbCA9IFdFRUspLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLAogICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gMTAqUEMxLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IDEwKlBDMiksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgxLzIsICdwaWNhcycpKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDEuMiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdGV4dChhZXMoeCA9IDExKlBDMSwKICAgICAgICAgICAgICAgIHkgPSAxMSpQQzIsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGR0LnJvdCRmZWF0KSwKICAgICAgICAgICAgIyBzaXplID0gNSwKICAgICAgICAgICAgaGp1c3QgPSAwLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMV0pICsKICBzY2FsZV95X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMl0pICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiV2VlayIpICsKICBnZ3RpdGxlKCJCaXBsb3Qgb2YgQW1pbm9hY2lkcyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvYW1pbm9hY2lkc19ieV93ZWVrX2JpcGxvdC50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMikKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAyKQpgYGAKCmBgYHtyIGFtaW5vYWNpZHNfYmlwbG90X2J5X3RydCwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KcDIgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDEwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAxMCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgIHNpemUgPSAxLjIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSAxMSpQQzEsCiAgICAgICAgICAgICAgICB5ID0gMTEqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlRyZWF0bWVudCIpICsKICBnZ3RpdGxlKCJCaXBsb3Qgb2YgQW1pbm9hY2lkcyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvYW1pbm9hY2lkc19ieV90cnRfYmlwbG90LnRpZmYiLAogICAgIGhlaWdodCA9IDEwLAogICAgIHdpZHRoID0gMTAsCiAgICAgdW5pdHMgPSAnaW4nLAogICAgIHJlcyA9IDMwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAyKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDIpCmBgYAojIFJlbW92ZSB1bm1hcHBlZCBPVFVzClRoZSAzMTEgdW5tYXBwZWQgT1RVcyB3ZXJlIHJlbW92ZWQgZnJvbSBmdXJ0aGVyIGFuYWx5c2lzICh3aXRoIDcsMjQ3IE9UVXMgbGVmdCkuCmBgYHtyIHJlbW92ZV91bm1hcHBlZF9vdHVfcGh5bHVtfQpwczEgPC0gc3Vic2V0X3RheGEocHMwLCAKICAgICAgICAgICAgICAgICAgICFpcy5uYShQaHlsdW0pKQpkaW0ocHMxQG90dV90YWJsZUAuRGF0YSkKYGBgCgojIENvdW50cyBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgY291bnRzX3AsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpjb3VudHNfcCA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJQaHlsdW0iKQpzZXRvcmRlcihjb3VudHNfcCwgLWAxOTA5MTktMDFgKQpkYXRhdGFibGUoY291bnRzX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KGNvdW50c19wKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyOm5jb2woY291bnRzX3ApLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMgUmVsYXRpdmUgYWJ1bmRhbmNlICglKSBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgcmFfcCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CnJhX3AgPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzID0gY291bnRzX3AsCiAgICAgICAgICAgICAgICAgICAgICAgcGN0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZGlnaXQgPSA0KQoKZGF0YXRhYmxlKHJhX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHJhX3ApKSkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMjpuY29sKGNvdW50c19wKSwKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKUmVtb3ZlIHBoeWxhIHdpdGggcmVsYXRpdmUgYWJ1bmRhbmNlIG9mID49IDElIGluIGxlc3MgdGhhbiAxMCUgb2Ygc2FtcGxlcy4KCmBgYHtyIHByZXZfcH0KdDEgPC0gZGF0YS50YWJsZShQaHlsdW0gPSByYV9wJFBoeWx1bSwKICAgICAgICAgICAgICAgICBgTnVtYmVyIG9mIFNhbXBsZXNgID0gcm93U3VtcyhyYV9wWywgMjpuY29sKHJhX3ApXSA+PSAwLjAxKSkKdDEkYFBlcmNlbnQgU2FtcGxlc2AgPC0gIHQxJGBOdW1iZXIgb2YgU2FtcGxlc2AvNzIKCnNldG9yZGVyKHQxLCAtYE51bWJlciBvZiBTYW1wbGVzYCkKZGF0YXRhYmxlKHQxLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMSkKYGBgCgpXZSB3aWxsIHJlbW92ZSBDaGxhbXlkaWFlIGZyb20gdGhpcyBhbmFseXNpcy4KCmBgYHtyIGtlZXBfcGh5bGEsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQprZWVwX3AgPC0gdDEkUGh5bHVtW3QxJGBQZXJjZW50IFNhbXBsZXNgID49IDAuMV0KIyAjIEtlZXAgYWxsCiMga2VlcF9wIDwtIHQxJFBoeWx1bQoKcGFzdGUwKGtlZXBfcCwgY29sbGFwc2UgPSAiLCAiKQoKcHMxIDwtIHN1YnNldF90YXhhKHBzMCwgCiAgICAgICAgICAgICAgICAgICBQaHlsdW0gJWluJSBrZWVwX3AgKQpvdHUxIDwtIGRhdGEudGFibGUocHMxQHRheF90YWJsZUAuRGF0YSwKICAgICAgICAgICAgICAgICAgIHQocHMxQG90dV90YWJsZUAuRGF0YSkpCgpkYXRhdGFibGUoaGVhZChvdHUxLCAxMCksCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA3Om5jb2wob3R1MSksCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKNywyMjQgT1RVcywgZG93biBmcm9tIDcsMjQ3IE9UVXMgaW4gdGhlIHByZXZpb3VzIHRhYmxlLgoKIyBSZWxhdGl2ZSBBYnVuZGFuY2UgaW4gU2FtcGxlcyBhdCBEaWZmZXJlbnQgVGF4b25vbWljIFJhbmtzCiMjIDEuIENsYXNzCmBgYHtyIGNvdW50c19jLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY291bnRzX2MgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIkNsYXNzIikKcmFfYyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfYykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNsYXNzIildKQoKcmFfYyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfYywKICAgICAgICAgICAgICBieSA9ICJDbGFzcyIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX2NbLCAzOm5jb2wocmFfYyldKQoKcmFfYyRDbGFzcyA8LSBmYWN0b3IocmFfYyRDbGFzcywKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfYyRDbGFzc1tvcmRlcih0b3RhbCldKQoKcmFfYyRQaHlsdW0gPC0gZmFjdG9yKHJhX2MkUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX2MkUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9jLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19jKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc21wbCRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNtcGwkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc21wbCRHZW5vdHlwZSksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IENsYXNzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDErCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19jLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX2MsCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGFzcyA9IGxyYSRDbGFzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJDbGFzcyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkNsYXNzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRDbGFzcyA8LSBmYWN0b3IobXUkQ2xhc3MsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJENsYXNzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKIyBQQ0EgYXQgQ2xhc3MgbGV2ZWwKYGBge3IgcGNhX2NfcDAsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA3fQpkdF9wY2EgPC0gdChyYV9jWywgMzpuY29sKHJhX2MpXSkKY29sbmFtZXMoZHRfcGNhKSA8LSByYV9jJENsYXNzCmR0X3BjYV9jIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSByb3duYW1lcyhkdF9wY2EpLAogICAgICAgICAgICAgICAgICAgICAgIGR0X3BjYSkKZHRfcGNhX2MgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICAgICAgZHRfcGNhX2MsCiAgICAgICAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gRkFMU0UsCiMgICAgICAgICAgICAgIHNjYWxlLiA9IEZBTFNFKQoKbTEgPC0gcHJjb21wKGR0X3BjYSkKc3VtbWFyeShtMSkKCgojIFNlbGVjdCBQQy1zIHRvIHBsaW90IChQQzEgJiBQQzIpCmNob2ljZXMgPC0gMToyCiMgU2NvcmVzLCBpLmUuIHBvaW50cyAoZGYudSkKZHQuc2NyIDwtIGRhdGEudGFibGUobTEkeFssIGNob2ljZXNdKQojIEFkZCBncm91cGluZyB2YXJpYWJsZQpkdC5zY3IkZ3JwIDwtIHBhc3RlKGR0X3BjYV9jJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICBkdF9wY2FfYyRXRUVLLAogICAgICAgICAgICAgICAgICAgIGR0X3BjYV9jJEdlbm90eXBlKQoKZHQuc2NyJFRSRUFUTUVOVCA8LSBkdF9wY2FfYyRUUkVBVE1FTlQKZHQuc2NyJFdFRUsgPC0gZHRfcGNhX2MkV0VFSwpkdC5zY3IkR2Vub3R5cGUgPC0gZHRfcGNhX2MkR2Vub3R5cGUKZHQuc2NyCgojIExvYWRpbmdzLCBpLmUuIGFycm93cyAoZGYudikKZHQucm90IDwtIGFzLmRhdGEuZnJhbWUobTEkcm90YXRpb25bLCBjaG9pY2VzXSkKZHQucm90JGZlYXQgPC0gcm93bmFtZXMoZHQucm90KQpkdC5yb3QgPC0gZGF0YS50YWJsZShkdC5yb3QpCmR0LnJvdAoKZHQubG9hZCA8LSBtZWx0LmRhdGEudGFibGUoZHQucm90LAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gImZlYXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAicGMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gImxvYWRpbmciKQpkdC5sb2FkJGZlYXQgPC0gZmFjdG9yKGR0LmxvYWQkZmVhdCwKICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUoZHQubG9hZCRmZWF0KSkKIyBQbG90IGxvYWRpbmdzCnAwIDwtIGdncGxvdChkYXRhID0gZHQubG9hZCwKICAgICAgICAgICAgIGFlcyh4ID0gZmVhdCwKICAgICAgICAgICAgICAgICB5ID0gbG9hZGluZykpICsKICBmYWNldF93cmFwKH4gcGMsCiAgICAgICAgICAgICBucm93ID0gMikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2d0aXRsZSgiUEMgTG9hZGluZ3MiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQp0aWZmKGZpbGVuYW1lID0gInRtcC9wYy4xLjJfbG9hZGluZ3NfY2xhc3MudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDgsCiAgICAgdW5pdHMgPSAnaW4nLAogICAgIHJlcyA9IDMwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgcGNhX2F4ZXNfY30KIyBBeGlzIGxhYmVscwp1LmF4aXMubGFicyA8LSBwYXN0ZShjb2xuYW1lcyhkdC5yb3QpWzE6Ml0sIAogICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCcoJTAuMWYlJSBleHBsYWluZWQgdmFyLiknLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMDAqbTEkc2RldltjaG9pY2VzXV4yL3N1bShtMSRzZGV2XjIpKSkKdS5heGlzLmxhYnMKYGBgCgpgYGB7ciBiaXBsb3RfZ3JwX2MsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gZ3JwKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDQwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSA0MCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgICMgc2l6ZSA9IDEsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSA0NCpQQzEsCiAgICAgICAgICAgICAgICB5ID0gNDQqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkdyb3VwIikgKwogIGdndGl0bGUoIkJpcGxvdCBvZiBDbGFzc2VzIG9mIEJhY3RlcmlhIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMjApKSAKdGlmZihmaWxlbmFtZSA9ICJ0bXAvY2xhc3NfYmlwbG90X2dycC50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIGJpcGxvdF9ncnBfd2l0aF9hdmdfYywgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBGaW5kIGNlbnRlcnMgb2YgZWFjaCBncm91cApncnBnIDwtICJncnAiCnZhcjEgPC0gZXZhbChwYXJzZSh0ZXh0ID0gcGFzdGUoImR0LnNjciQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdycGcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIiIpKSkKCmNudHIgPC0gZGF0YS50YWJsZShHcm91cCA9IHVuaXF1ZSh2YXIxKSwKICAgICAgICAgICAgICAgICAgIFBDMSA9IGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4LAogICAgICAgICAgICAgICAgICAgUEMyID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdCh2YXIxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCnAyIDwtIHAxICsgZ2VvbV9sYWJlbChkYXRhID0gY250ciwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBQQzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBHcm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoZ3VpZGUgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKcHJpbnQocDIpCmBgYAoKYGBge3IgYmlwbG90X2dlbm90eXBlX2MsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gR2Vub3R5cGUpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLAogICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gNDAqUEMxLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IDQwKlBDMiksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgxLzIsICdwaWNhcycpKSwKICAgICAgICAgICAgICAgIyBzaXplID0gMSwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdGV4dChhZXMoeCA9IDQ0KlBDMSwKICAgICAgICAgICAgICAgIHkgPSA0NCpQQzIsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGR0LnJvdCRmZWF0KSwKICAgICAgICAgICAgIyBzaXplID0gNSwKICAgICAgICAgICAgaGp1c3QgPSAwLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMV0pICsKICBzY2FsZV95X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMl0pICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiR3JvdXAiKSArCiAgZ2d0aXRsZSgiQmlwbG90IG9mIENsYXNzZXMgb2YgQmFjdGVyaWEiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAyMCkpCnRpZmYoZmlsZW5hbWUgPSAidG1wL2NsYXNzX2JpcGxvdF9nZW5vdHlwZS50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIGJpcGxvdF9nZW5vdHlwZV93aXRoX2F2Z19jLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIEZpbmQgY2VudGVycyBvZiBlYWNoIGdyb3VwCmdycGcgPC0gIkdlbm90eXBlIgp2YXIxIDwtIGV2YWwocGFyc2UodGV4dCA9IHBhc3RlKCJkdC5zY3IkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncnBnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSkpCgpjbnRyIDwtIGRhdGEudGFibGUoR3JvdXAgPSB1bmlxdWUodmFyMSksCiAgICAgICAgICAgICAgICAgICBQQzEgPSBhZ2dyZWdhdGUoeCA9IGR0LnNjciRQQzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KHZhcjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikkeCwKICAgICAgICAgICAgICAgICAgIFBDMiA9IGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4KQpwMiA8LSBwMSArIGdlb21fbGFiZWwoZGF0YSA9IGNudHIsCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gR3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGd1aWRlID0gRkFMU0UpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCnByaW50KHAyKQpgYGAKCmBgYHtyIGJpcGxvdF93ZWVrX2MsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gV0VFSyksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IDAsCiAgICAgICAgICAgICAgICAgICB5ID0gMCwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSA0MCpQQzEsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gNDAqUEMyKSwKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDEvMiwgJ3BpY2FzJykpLAogICAgICAgICAgICAgICAjIHNpemUgPSAxLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gNDQqUEMxLAogICAgICAgICAgICAgICAgeSA9IDQ0KlBDMiwKICAgICAgICAgICAgICAgIGxhYmVsID0gZHQucm90JGZlYXQpLAogICAgICAgICAgICAjIHNpemUgPSA1LAogICAgICAgICAgICBoanVzdCA9IDAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyh1LmF4aXMubGFic1sxXSkgKwogIHNjYWxlX3lfY29udGludW91cyh1LmF4aXMubGFic1syXSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJHcm91cCIpICsKICBnZ3RpdGxlKCJCaXBsb3Qgb2YgQ2xhc3NlcyBvZiBCYWN0ZXJpYSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvY2xhc3NfYmlwbG90X3dlZWsudGlmZiIsCiAgICAgaGVpZ2h0ID0gMTAsCiAgICAgd2lkdGggPSAxMCwKICAgICB1bml0cyA9ICdpbicsCiAgICAgcmVzID0gMzAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBiaXBsb3Rfd2Vla193aXRoX2F2Z19jLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIEZpbmQgY2VudGVycyBvZiBlYWNoIGdyb3VwCmdycGcgPC0gIldFRUsiCnZhcjEgPC0gZXZhbChwYXJzZSh0ZXh0ID0gcGFzdGUoImR0LnNjciQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdycGcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIiIpKSkKCmNudHIgPC0gZGF0YS50YWJsZShHcm91cCA9IHVuaXF1ZSh2YXIxKSwKICAgICAgICAgICAgICAgICAgIFBDMSA9IGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4LAogICAgICAgICAgICAgICAgICAgUEMyID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdCh2YXIxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCnAyIDwtIHAxICsgZ2VvbV9sYWJlbChkYXRhID0gY250ciwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBQQzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBHcm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoZ3VpZGUgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKcHJpbnQocDIpCmBgYAoKYGBge3IgYmlwbG90X3RydF9jLCBmaWcuaGVpZ2h0ID0gOCwgZmlnLndpZHRoID0gOH0KIyBCYXNlZCBvbiBGaWd1cmUgcDAsIGtlZXAgb25seSBhIGZldyB2YXJpYWJsZXMgd2l0aCBoaWdoIGxvYWRpbmdzIGluIFBDMSBhbmQgUEMyLS0tLQojIHZhci5rZWVwLm5keCA8LSB3aGljaChkdC5yb3QkZmVhdCAlaW4lIGMoLi4uKSkKIyBPciBzZWxlY3QgYWxsCiMgdmFyLmtlZXAubmR4IDwtIDM6bmNvbChkdDEpCiMgVXNlIGR0LnJvdFt2YXIua2VlcC5uZHgsXSBhbmQgZHQucm90JGZlYXRbdmFyLmtlZXAubmR4XQoKcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDQwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSA0MCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgICMgc2l6ZSA9IDEsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSA0NCpQQzEsCiAgICAgICAgICAgICAgICB5ID0gNDQqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJUcmVhdG1lbnQiLAogICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGxldmVscyhkdC5zY3IkVFJFQVRNRU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvcmFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJibHVlIikpICsKICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIkJpcGxvdCBvZiBDbGFzc2VzIG9mIEJhY3RlcmlhIikgKwogICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKICAgICAgICAgICAgICAgICAgICBnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBiaXBsb3RfdHJ0X3dpdGhfYXZnX2MsIGZpZy5oZWlnaHQgPSA4LCBmaWcud2lkdGggPSA4fQojIEZpbmQgY2VudGVycyBvZiBlYWNoIGdyb3VwCiMgZ3JwZyA8LSAiVFJFQVRNRU5UIgojIHZhcjEgPC0gZXZhbChwYXJzZSh0ZXh0ID0gcGFzdGUoImR0LnNjciQiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JwZywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSkpCgojIGNudHIgPC0gZGF0YS50YWJsZShHcm91cCA9IGxldmVscyh2YXIxKSwKIyAgICAgICAgICAgICAgICAgICAgUEMxID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMxLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KHZhcjEpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4LAojICAgICAgICAgICAgICAgICAgICBQQzIgPSBhZ2dyZWdhdGUoeCA9IGR0LnNjciRQQzIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCgpjbnRyIDwtIGRhdGEudGFibGUoUEMxID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChkdC5zY3IkVFJFQVRNRU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpLAogICAgICAgICAgICAgICAgICAgUEMyID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdCh2YXIxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCmNvbG5hbWVzKGNudHIpIDwtIGMoIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgIlBDMSIsCiAgICAgICAgICAgICAgICAgICAgIlBDMiIpCgpwMiA8LSBwMSArIGdlb21fbGFiZWwoZGF0YSA9IGNudHIsCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IFRSRUFUTUVOVCksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGd1aWRlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gbGV2ZWxzKGNudHIkVFJFQVRNRU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvcmFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJibHVlIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC9jbGFzc19iaXBsb3RfdHJ0LnRpZmYiLAogICAgIGhlaWdodCA9IDgsCiAgICAgd2lkdGggPSA4LAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMikKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAyKQpgYGAKCmBgYHtyIG11bHRpbm9tX2N9CiMgQ292YXJpYXRlcyBvbmx5Cm0xIDwtIG11bHRpbm9tKFRSRUFUTUVOVCB+IFdFRUsgKyBHZW5vdHlwZSwKICAgICAgICAgICAgICAgZGF0YSA9IGR0LnNjcikKc3VtbWFyeShtMSkKCnByZDEgPC0gcHJlZGljdChtMSkKCnQxIDwtIHRhYmxlKFByZWRpY3RlZCA9IHByZDEsCiAgICAgICAgICAgIE9ic2VydmVkID0gZHQuc2NyJFRSRUFUTUVOVCkKCiMgUEMxIGFsb25lCm0yIDwtIG11bHRpbm9tKFRSRUFUTUVOVCB+IFBDMSwKICAgICAgICAgICAgICAgZGF0YSA9IGR0LnNjcikKc3VtbWFyeShtMikKCnByZDIgPC0gcHJlZGljdChtMikKCnQyIDwtIHRhYmxlKFByZWRpY3RlZCA9IHByZDIsCiAgICAgICAgICAgIE9ic2VydmVkID0gZHQuc2NyJFRSRUFUTUVOVCkKCiMgUEMxIHdpdGggY292YXJpYXRlcwptMyA8LSBtdWx0aW5vbShUUkVBVE1FTlQgfiBQQzEgKyBXRUVLICsgR2Vub3R5cGUsCiAgICAgICAgICAgICAgIGRhdGEgPSBkdC5zY3IpCnN1bW1hcnkobTMpCgpwcmQzIDwtIHByZWRpY3QobTMpCgp0MyA8LSB0YWJsZShQcmVkaWN0ZWQgPSBwcmQzLAogICAgICAgICAgICBPYnNlcnZlZCA9IGR0LnNjciRUUkVBVE1FTlQpCgojIFBDMSArIFBDMiB3aXRoIGNvdmFyaWF0ZXMKbTQgPC0gbXVsdGlub20oVFJFQVRNRU5UIH4gUEMxICsgUEMyICsgV0VFSyArIEdlbm90eXBlLAogICAgICAgICAgICAgICBkYXRhID0gZHQuc2NyKQpzdW1tYXJ5KG00KQoKcHJkNCA8LSBwcmVkaWN0KG00KQoKdDQgPC0gdGFibGUoUHJlZGljdGVkID0gcHJkNCwKICAgICAgICAgICAgT2JzZXJ2ZWQgPSBkdC5zY3IkVFJFQVRNRU5UKQoKIyBDb25mdXNpb24gdGFibGVzCmRhdGF0YWJsZShjYmluZCh0MSksIAogICAgICAgICAgY2FwdGlvbiA9ICJDb3ZhcmlhdGVzIE9ubHkiKQpkYXRhdGFibGUoY2JpbmQodDIpLAogICAgICAgICAgY2FwdGlvbiA9ICJQQzEgT25seSIpCmRhdGF0YWJsZShjYmluZCh0MyksCiAgICAgICAgICBjYXB0aW9uID0gIlBDMSB3aXRoIGNvdmFyaWF0ZXMiKQpkYXRhdGFibGUoY2JpbmQodDQpLAogICAgICAgICAgY2FwdGlvbiA9ICJQQzEgKyBQQzIgd2l0aCBjb3ZhcmlhdGVzIikKCiMgQ29tcGFyZSBtb2RlbHMKYW5vdmEobTEsIG0zKQphbm92YShtMiwgbTMpCmFub3ZhKG00LCBtMykKYGBgCgpUaGUgcmVzdWx0cyBzdWdnZXN0IHRoYXQ6ICAKYS4gQ292YXJpYXRlcyBhbG9uZSAodGltZXBvaW50IGFuZCBnZW5vdHlwZSkgY2Fubm90IGV4cGxhaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0cmVhdG1lbnRzLiAgCmIuIFByaW5jaXBhbCBDb21wb25lbnQgMSAoUEMxKSBjYW4gZXhwbGFpbiB0aGUgZGlmZmVyZW5jZXMgaW4gcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIGNsYXNzZXMgaW4gdGhlIHNhbXBsZXMuIFRoZSBtb2RlbCBkb2VzIG5vdCBpbXByb3ZlIHNpZ25pZmljYW50bHkgYnkgYWRkaW5nIHRoZSBjb3ZhcmlhdGVzIG9yIHRoZSBQQzIuIEhvd2V2ZXIsIHRoZSBjb3ZhcmlhdGVzIHNob3VsZCBzdGF5IGluIHRoZSBtb2RlbCBmb3IgYWRqdXN0bWVudCwgYW5kIFBDMiBzbGlnaHRseSBpbXByb3ZlcyB0aGUgcHJlZGljdGlvbnMuICAKYy4gVGhlIGZ1bGwgbW9kZWwgKFBDMSArIFBDMiArIFdlZWsgKyBHZW5vdHlwZSkgY29ycmVjdGx5IGNsYXNzaWZpZXMgMTIgb3V0IG9mIDE4IE5haXZlIHNhbXBsZXMsIGFuZCAxMiBvdXQgb2YgMTggRFNTK0NyYW5idXJyeSBzYW1wbGVzLiAgCiAgCkNvbnRpbnVpbmcgdGhlIHNhbWUgYW5hbHlzaXMgYXQgT3JkZXIsIEZhbWlseSBhbmQgR2VudXMgbGV2ZWxzLgoKRE8gUk9DIEFVQyBORVNUISEhCmBgYHtyIHJvY19GUk9NX0tFQVAxTlJGMl9TVFVEWSwgaGVpZ2h0ID0gNyxmaWcud2lkdGggPSA4fQojICMgT3V0cHV0IHByb2JvYmlsaXRpZXMtLS0tCiMgcHJkMS4xIDwtIHByZWRpY3QobTEsCiMgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJwcm9icyIpCiMgcHJkMS4xIDwtIGRhdGEudGFibGUoSUQgPSBkZi51JElELAojICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGRmLnUkVHJlYXRtZW50LAojICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHByZDEuMSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICA0KSkKIyAKIyBwcmQyLjEgPC0gcHJlZGljdChtMiwKIyAgICAgICAgICAgICAgICAgICB0eXBlID0gInByb2JzIikKIyBwcmQyLjEgPC0gZGF0YS50YWJsZShJRCA9IGRmLnUkSUQsCiMgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gZGYudSRUcmVhdG1lbnQsCiMgICAgICAgICAgICAgICAgICAgICAgcm91bmQocHJkMi4xLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQpKQojIAojICMgU2Vuc2l0aXZpdHkvU3BlY2lmaWNpdHkKIyAjIFRyZXNob2xkcwojIHRyaGQgPC0gc2VxKDAsIDEsIGJ5ID0gMC4wMSkKIyAKIyBvdXQxIDwtIGxpc3QoKQojIGZvciAoaSBpbiAxOmxlbmd0aCh0cmhkKSkgewojICAgdG1wIDwtIGFwcGx5KHByZDEuMVssIC1jKDE6MildLAojICAgICAgICAgICAgICAgIE1BUkdJTiA9IDIsCiMgICAgICAgICAgICAgICAgRlVOID0gZnVuY3Rpb24oYSkgewojICAgICAgICAgICAgICAgICAgcmV0dXJuKGEgPj0gdHJoZFtpXSkKIyAgICAgICAgICAgICAgICB9KQojICAgdG1wMiA8LSBhcHBseShYID0gdG1wLAojICAgICAgICAgICAgICAgICBNQVJHSU4gPSAyLAojICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbihhKSB7CiMgICAgICAgICAgICAgICAgICAgYWdncmVnYXRlKHggPSBhLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QocHJkMS4xJFRyZWF0bWVudCksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IHN1bSkkeAojICAgICAgICAgICAgICAgICB9KQojICAgdG1wMgojICAgb3V0MVtbaV1dIDwtIGMoc2VucyA9IHN1bShkaWFnKHRtcDIpKS9ucm93KHByZDEuMSksCiMgICAgICAgICAgICAgICAgICBzcGVjID0gKHN1bSh0bXAyW3VwcGVyLnRyaSh0bXAyKV0pICsgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKHRtcDJbbG93ZXIudHJpKHRtcDIpXSkpLyhucm93KHRtcCkqKG5jb2wodG1wKSAtIDEpKSkKIyB9CiMgb3V0MSA8LSBkYXRhLnRhYmxlKGRvLmNhbGwoInJiaW5kIiwgb3V0MSkpCiMgb3V0MSA8LSB1bmlxdWUob3V0MSkKIyAKIyBvdXQyIDwtIGxpc3QoKQojIGZvciAoaSBpbiAxOmxlbmd0aCh0cmhkKSkgewojICAgdG1wIDwtIGFwcGx5KHByZDIuMVssIC1jKDE6MildLAojICAgICAgICAgICAgICAgIE1BUkdJTiA9IDIsCiMgICAgICAgICAgICAgICAgRlVOID0gZnVuY3Rpb24oYSkgewojICAgICAgICAgICAgICAgICAgcmV0dXJuKGEgPj0gdHJoZFtpXSkKIyAgICAgICAgICAgICAgICB9KQojICAgdG1wMiA8LSBhcHBseShYID0gdG1wLAojICAgICAgICAgICAgICAgICBNQVJHSU4gPSAyLAojICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbihhKSB7CiMgICAgICAgICAgICAgICAgICAgYWdncmVnYXRlKHggPSBhLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QocHJkMi4xJFRyZWF0bWVudCksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IHN1bSkkeAojICAgICAgICAgICAgICAgICB9KQojICAgb3V0MltbaV1dIDwtIGMoc2VucyA9IHN1bShkaWFnKHRtcDIpKS9ucm93KHByZDIuMSksCiMgICAgICAgICAgICAgICAgICBzcGVjID0gKHN1bSh0bXAyW3VwcGVyLnRyaSh0bXAyKV0pICsgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKHRtcDJbbG93ZXIudHJpKHRtcDIpXSkpLyhucm93KHRtcCkqKG5jb2wodG1wKSAtIDEpKSkKIyB9CiMgb3V0MiA8LSBkYXRhLnRhYmxlKGRvLmNhbGwoInJiaW5kIiwgb3V0MikpCiMgb3V0MiA8LSB1bmlxdWUob3V0MikKIyAKIyAjIFJPQwojIHJvYzEgPC0gYXVjKHggPSBvdXQxJHNwZWMsCiMgICAgICAgICAgICAgeSA9IG91dDEkc2VucywKIyAgICAgICAgICAgICBmcm9tID0gMCwKIyAgICAgICAgICAgICB0byA9IDEpCiMgCiMgcm9jMiA8LSBhdWMoeCA9IG91dDIkc3BlYywKIyAgICAgICAgICAgICB5ID0gb3V0MiRzZW5zLAojICAgICAgICAgICAgIGZyb20gPSAwLAojICAgICAgICAgICAgIHRvID0gMSkKIyAKIyAjIFJPQyBwbG90CiMgcGxvdChvdXQxJHNlbnMgfiBvdXQxJHNwZWMsCiMgICAgICB0eXBlID0gImwiLAojICAgICAgeGxpbSA9IGMoMCwgMSksCiMgICAgICB5bGltID0gYygwLCAxKSwKIyAgICAgIHhsYWIgPSAiMSAtIFNwZWNpZmljaXR5IiwKIyAgICAgIHlsYWIgPSAiU2Vuc2l0aXZpdHkiLAojICAgICAgY29sID0gImJsdWUiKQojIGxpbmVzKG91dDIkc2VucyB+IG91dDIkc3BlYywKIyAgICAgICBjb2wgPSAicmVkIikKIyB0ZXh0KHggPSBjKDAuOCwgMC44KSwKIyAgICAgIHkgPSBjKDAuMiwgMC4zKSwKIyAgICAgIGxhYmVsID0gYyhwYXN0ZSgiUk9DKFBDMSkgPSAiLAojICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJvYzEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIDMpKSwKIyAgICAgICAgICAgICAgICBwYXN0ZSgiXG5ST0MoUEMxK1BDMikgPSAiLAojICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJvYzIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgMykpKSwKIyAgICAgIGNvbCA9IGMoImJsdWUiLAojICAgICAgICAgICAgICAicmVkIikpCiMgYWJsaW5lKDAsIDEsIGx0eSA9IDIpCmBgYAoKYGBge3IgbWVhbnNfY19wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCgpwMCA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IENsYXNzLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV95IikgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gVHJ0X0dlbm90eXBlKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9jbGFzc19vdmVyX3RpbWUudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgbWVhbnNfY19wMSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDl9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gQ2xhc3MsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcnRfR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9jbGFzc19yYS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCiMjIDIuIE9yZGVyCmBgYHtyIGNvdW50c19vLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY291bnRzX28gPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIk9yZGVyIikKcmFfbyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfbykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9yZGVyIildKQoKcmFfbyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfbywKICAgICAgICAgICAgICBieSA9ICJPcmRlciIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX29bLCAzOm5jb2wocmFfbyldKQoKcmFfbyRPcmRlciA8LSBmYWN0b3IocmFfbyRPcmRlciwKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfbyRPcmRlcltvcmRlcih0b3RhbCldKQoKcmFfbyRQaHlsdW0gPC0gZmFjdG9yKHJhX28kUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX28kUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9vLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19vKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc21wbCRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNtcGwkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc21wbCRHZW5vdHlwZSksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IE9yZGVyLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDErCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19vLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX28sCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmRlciA9IGxyYSRPcmRlciksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJPcmRlciJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIk9yZGVyIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRPcmRlciA8LSBmYWN0b3IobXUkT3JkZXIsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJE9yZGVyKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKYGBge3IgbWVhbnNfb19wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCgpwMCA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IE9yZGVyLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV95IikgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gVHJ0X0dlbm90eXBlKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9PcmRlcl9vdmVyX3RpbWUudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgbWVhbnNfb19wMSwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDd9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gT3JkZXIsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcnRfR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X09yZGVyX3JhLnRpZmYiLAogICAgIGhlaWdodCA9IDQsCiAgICAgd2lkdGggPSA3LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxICsKICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCiMjIDMuIEZhbWlseQpgYGB7ciBjb3VudHNfZiwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZmlnLndpZHRoPTE1LGZpZy5oZWlnaHQ9MTV9CmNvdW50c19mIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJGYW1pbHkiKQpyYV9mIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50c19mKQoKdGF4LnJhbmtzIDwtIHVuaXF1ZShvdHUxWywgYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFtaWx5IildKQoKcmFfZiA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfZiwKICAgICAgICAgICAgICBieSA9ICJGYW1pbHkiKQoKdG90YWwgPC0gcm93U3VtcyhyYV9mWywgMzpuY29sKHJhX2YpXSkKCnJhX2YkRmFtaWx5IDwtIGZhY3RvcihyYV9mJEZhbWlseSwKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfZiRGYW1pbHlbb3JkZXIodG90YWwpXSkKCnJhX2YkUGh5bHVtIDwtIGZhY3RvcihyYV9mJFBoeWx1bSwKICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShyYV9mJFBoeWx1bVtvcmRlcih0b3RhbCldKSkKdG1wIDwtIG1lbHQuZGF0YS50YWJsZShkYXRhID0gcmFfZiwKICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUudmFycyA9IDM6bmNvbChjb3VudHNfZiksCiAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICJTQU1QTEVfTkFNRSIsCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJSQSIpCgp0bXAgPC0gbWVyZ2UoZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHNtcGwkU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgICAgICAgIFdFRUsgPSBzbXBsJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNtcGwkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IHNtcGwkR2Vub3R5cGUpLAogICAgICAgICAgICAgdG1wLAogICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKIyBQbG90IHNhbXBsZXMKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFJBLAogICAgICAgICAgICAgICAgIGZpbGwgPSBGYW1pbHksCiAgICAgICAgICAgICAgICAgY29sb3IgPSBQaHlsdW0pKSArCiAgZmFjZXRfd3JhcCh+IFdFRUsgKyBUUkVBVE1FTlQgKyBHZW5vdHlwZSwKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlX3giLAogICAgICAgICAgICAgbnJvdyA9IDMpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQpnZ3Bsb3RseShwMSsKICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCmBgYHtyIG1lYW5zX2YsIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmxyYSA8LSByYV9tZWx0KHJhID0gcmFfZiwKICAgICAgICAgICAgICAgc2FtcGxlcyA9IHNtcGwsCiAgICAgICAgICAgICAgIHNhbXBsZV9uYW1lID0gIlNBTVBMRV9OQU1FIikKCm11IDwtIGRhdGEudGFibGUoYWdncmVnYXRlKGxyYSRSQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KFdlZWsgPSBscmEkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGxyYSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IGxyYSRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZhbWlseSA9IGxyYSRGYW1pbHkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpKQptdVssIHRvdGFsIDo9IHN1bSh4KSwKICAgYnkgPSAiRmFtaWx5Il0KdWwgPC0gdW5pcXVlKG11WywgYygiRmFtaWx5IiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRGYW1pbHkgPC0gZmFjdG9yKG11JEZhbWlseSwKICAgICAgICAgICAgICAgICAgIGxldmVsID0gdWwkRmFtaWx5KQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIEZhbWlseSA9IGxpc3QobGlzdCgzLCAnZGVzYycpKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA1LAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKCk5PVEU6IG9ubHkgdGhlIGZpcnN0IDI0IGZhbWlsaWVzIGhhZCBsYXJnZSBlbm91Z2ggY291bnRzIC0gcGxvdGluZyBvbmx5IHRoZW0uICAKICAKYGBge3IgbWVhbnNfZl9wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCm11MSA8LSBkcm9wbGV2ZWxzKG11W0ZhbWlseSAlaW4lIGxldmVscyhtdSRGYW1pbHkpW25sZXZlbHMobXUkRmFtaWx5KToobmxldmVscyhtdSRGYW1pbHkpIC0gMjQpXSwgXSkKCnAwIDwtIGdncGxvdChtdTEsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IEZhbWlseSwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFRydF9HZW5vdHlwZSksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfRmFtaWx5X292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA3LAogICAgIHdpZHRoID0gOSwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgpgYGB7ciBtZWFuc19mX3AxLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gOX0KcDEgPC0gZ2dwbG90KG11MSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gRmFtaWx5LAogICAgICAgICAgICAgICAgIGNvbG9yID0gVHJ0X0dlbm90eXBlLAogICAgICAgICAgICAgICAgIHNoYXBlID0gV2VlaykpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLAogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHNjYWxlX3hfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X0ZhbWlseV9yYS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSsKICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCiMjIDQuIEdlbnVzCmBgYHtyIGNvdW50c19nLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY291bnRzX2cgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIkdlbnVzIikKcmFfZyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfZykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdlbnVzIildKQoKcmFfZyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfZywKICAgICAgICAgICAgICBieSA9ICJHZW51cyIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX2dbLCAzOm5jb2wocmFfZyldKQoKcmFfZyRHZW51cyA8LSBmYWN0b3IocmFfZyRHZW51cywKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfZyRHZW51c1tvcmRlcih0b3RhbCldKQoKcmFfZyRQaHlsdW0gPC0gZmFjdG9yKHJhX2ckUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX2ckUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9nLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19nKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc21wbCRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNtcGwkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc21wbCRHZW5vdHlwZSksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IEdlbnVzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDErCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19nLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX2csCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW51cyA9IGxyYSRHZW51cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJHZW51cyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkdlbnVzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRHZW51cyA8LSBmYWN0b3IobXUkR2VudXMsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJEdlbnVzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIEdlbnVzID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKYGBge3IgbWVhbnNfZ19wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCm11MSA8LSBkcm9wbGV2ZWxzKG11W0dlbnVzICVpbiUgbGV2ZWxzKG11JEdlbnVzKVtubGV2ZWxzKG11JEdlbnVzKToobmxldmVscyhtdSRHZW51cykgLSAzNSldLCBdKQoKcDAgPC0gZ2dwbG90KG11MSwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0geCwKICAgICAgICAgICAgICAgICBncm91cCA9IFRydF9HZW5vdHlwZSkpICsKICBmYWNldF93cmFwKH4gR2VudXMsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZ2VvbV9saW5lKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBUcnRfR2Vub3R5cGUpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X0dlbnVzX292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA5LAogICAgIHdpZHRoID0gMTIsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDArCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19nX3AxLCBmaWcuaGVpZ2h0ID0gOSwgZmlnLndpZHRoID0gOX0KcDEgPC0gZ2dwbG90KG11MSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gR2VudXMsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcnRfR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfR2VudXNfcmEudGlmZiIsCiAgICAgaGVpZ2h0ID0gOSwKICAgICB3aWR0aCA9IDksCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDErCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgojIFNlc3Npb24gSW5mb3JtYXRpb24KYGBge3IgaW5mbyxldmFsPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBg